function renderEntitySummary($cell, $title, $values = array()) { global $page_by_realm; // allow plugins to override summary table $values = callHook('modifyEntitySummary', $cell, $values); startPortlet($title); echo "<table border=0 cellspacing=0 cellpadding=3 width='100%'>\n"; foreach ($values as $name => $value) { if (is_array($value) and count($value) == 1) { $value = array_shift($value); echo $value; continue; } if (is_array($value)) { $name = array_shift($value); $value = array_shift($value); } elseif (!is_array($value)) { $name .= ':'; } $class = 'tdright'; $m = array(); if (preg_match('/^\\{(.*?)\\}(.*)/', $name, $m)) { $class .= ' ' . $m[1]; $name = $m[2]; } if ($name == 'tags:') { $baseurl = ''; if (isset($page_by_realm[$cell['realm']])) { $baseurl = makeHref(array('page' => $page_by_realm[$cell['realm']], 'tab' => 'default')) . "&"; } printTagTRs($cell, $baseurl); } else { echo "<tr><th width='50%' class='{$class}'>{$name}</th><td class=tdleft>{$value}</td></tr>"; } } echo "</table>\n"; finishPortlet(); }
function generateSLBConfig2($triplet_list) { $ret = ''; global $parser_class; $gl_parser = new $parser_class(); $defaults = getSLBDefaults(TRUE); $gl_parser->addMacro('GLOBAL_VS_CONF', dos2unix($defaults['vsconfig'])); $gl_parser->addMacro('GLOBAL_RS_CONF', dos2unix($defaults['rsconfig'])); $gl_parser->addMacro('RSPORT', '%VPORT%'); $gl_parser->addMacro('VS_PREPEND', "# LB (id == %LB_ID%): %LB_NAME%\n# VSG (id == %VSG_ID%): %VS_NAME%\n# RS (id == %RSP_ID%): %RSP_NAME%"); // group triplets by object_id, vs_id $grouped = array(); foreach ($triplet_list as $triplet) { $grouped[$triplet['object_id']][$triplet['vs_id']][] = $triplet; } foreach ($grouped as $object_id => $subarr) { $seen_vs_groups = array(); $lb_parser = clone $gl_parser; $lb_cell = spotEntity('object', $object_id); $lb_parser->addMacro('LB_ID', $lb_cell['id']); $lb_parser->addMacro('LB_NAME', $lb_cell['name']); foreach ($subarr as $vs_id => $triplets) { $vs_parser = clone $lb_parser; $vs_cell = spotEntity('ipvs', $vs_id); if (!isset($vs_cell['ports']) || !isset($vs_cell['vips'])) { amplifyCell($vs_cell); } $vs_parser->addMacro('VS_ID', $vs_cell['id']); $vs_parser->addMacro('VSG_ID', $vs_cell['id']); $vs_parser->addMacro('VS_NAME', $vs_cell['name']); $vs_parser->addMacro('VS_RS_CONF', dos2unix($vs_cell['rsconfig'])); foreach ($triplets as $triplet) { $virtual_services = array(); $tr_parser = clone $vs_parser; $rs_cell = spotEntity('ipv4rspool', $triplet['rspool_id']); $tr_parser->addMacro('RSP_ID', $rs_cell['id']); $tr_parser->addMacro('RSP_NAME', $rs_cell['name']); $tr_parser->addMacro('RSP_VS_CONF', dos2unix($rs_cell['vsconfig'])); $tr_parser->addMacro('RSP_RS_CONF', dos2unix($rs_cell['rsconfig'])); $tr_parser->addMacro('VS_VS_CONF', dos2unix($vs_cell['vsconfig'])); // VS-driven vsconfig has higher priority than RSP-driven foreach ($triplet['ports'] as $port_row) { $is_mark = $port_row['proto'] == 'MARK'; $p_parser = clone $tr_parser; $p_parser->addMacro('VS_HEADER', $is_mark ? 'fwmark %MARK%' : '%VIP% %VPORT%'); $p_parser->addMacro('PROTO', $is_mark ? 'TCP' : $port_row['proto']); $p_parser->addMacro($is_mark ? 'MARK' : 'VPORT', $port_row['vport']); foreach ($vs_cell['ports'] as $vport) { if ($vport['vport'] == $port_row['vport'] && $vport['proto'] == $port_row['proto']) { $p_parser->addMacro('PORT_VS_CONF', dos2unix($vport['vsconfig'])); $p_parser->addMacro('PORT_RS_CONF', dos2unix($vport['rsconfig'])); break; } } $p_parser->addMacro('SLB_PORT_VS_CONF', dos2unix($port_row['vsconfig'])); $p_parser->addMacro('SLB_PORT_RS_CONF', dos2unix($port_row['rsconfig'])); if ($is_mark) { $p_parser->addMacro('RS_HEADER', '%RSIP%'); // find enabled IP families to fill IP_VER $seen_families = array(); foreach ($triplet['vips'] as $ip_row) { $family_length = strlen($ip_row['vip']); $seen_families[$family_length] = $family_length == 16 ? 6 : 4; } if (!$seen_families) { $seen_families['unknown'] = ''; } foreach ($seen_families as $ip_ver) { $fam_parser = clone $p_parser; if ($ip_ver) { $fam_parser->addMacro('IP_VER', $ip_ver); } if ('' != ($vs_config = generateVSSection($fam_parser))) { $virtual_services["IPv{$ip_ver} " . $fam_parser->expandMacro('VS_HEADER')] = $vs_config; } } } else { $p_parser->addMacro('RS_HEADER', '%RSIP% %RSPORT%'); foreach ($triplet['vips'] as $ip_row) { $ip_parser = clone $p_parser; $ip_parser->addMacro('VIP', ip_format($ip_row['vip'])); $ip_parser->addMacro('IP_VER', strlen($ip_row['vip']) == 16 ? 6 : 4); $ip_parser->addMacro('PRIO', $ip_row['prio']); foreach ($vs_cell['vips'] as $vip) { if ($vip['vip'] === $ip_row['vip']) { $ip_parser->addMacro('VIP_VS_CONF', dos2unix($vip['vsconfig'])); $ip_parser->addMacro('VIP_RS_CONF', dos2unix($vip['rsconfig'])); break; } } $ip_parser->addMacro('SLB_VIP_VS_CONF', dos2unix($ip_row['vsconfig'])); $ip_parser->addMacro('SLB_VIP_RS_CONF', dos2unix($ip_row['rsconfig'])); if ('' != ($vs_config = generateVSSection($ip_parser))) { $virtual_services[$port_row['proto'] . " " . $ip_parser->expandMacro('VS_HEADER')] = $vs_config; } } // vips } } //ports // group multiple virtual_services into vs_groups $groups = array(); foreach ($virtual_services as $key => $content) { $groups[$content][] = preg_replace('/^(TCP|UDP|IPv[46]?)\\s+/', '', $key); } foreach ($groups as $content => $keys) { if (NULL !== ($new_content = callHook('generateSLBConfig_stage2', $content, $keys))) { $content = $new_content; } $ret .= $tr_parser->expand("\n%VS_PREPEND%\n"); if (count($keys) == 1) { $ret .= "virtual_server " . array_first($keys) . " {\n" . $content . "}\n"; } else { // come up with the name for new VS group $vsg_name = makeUniqueVSGName($seen_vs_groups, $keys, $vs_cell); $seen_vs_groups[$vsg_name] = 1; $tr_parser->addMacro('VSG_NAME', $vsg_name); $ret .= $tr_parser->expand("virtual_server_group %VSG_NAME% {\n"); foreach ($keys as $vs_header) { $ret .= "\t{$vs_header}\n"; } $ret .= "}\n"; $ret .= $tr_parser->expand("virtual_server group %VSG_NAME% {\n"); $ret .= $content . "}\n"; } } } // triplets } // vs } // balancers return $ret; }
function doVSMigrate() { global $dbxlink; $vs_id = assertUIntArg('vs_id'); $vs_cell = spotEntity('ipvs', $vs_id); amplifyCell($vs_cell); $tag_ids = genericAssertion('taglist', 'array0'); $old_vs_list = genericAssertion('vs_list', 'array'); $plan = callHook('buildVSMigratePlan', $vs_id, $old_vs_list); $dbxlink->beginTransaction(); // remove all triplets usePreparedDeleteBlade('VSEnabledIPs', array('vs_id' => $vs_id)); usePreparedDeleteBlade('VSEnabledPorts', array('vs_id' => $vs_id)); // remove all VIPs and ports that are in $plan and create new ones foreach ($plan['vips'] as $vip) { usePreparedDeleteBlade('VSIPs', array('vs_id' => $vs_id, 'vip' => $vip['vip'])); usePreparedInsertBlade('VSIPs', array('vs_id' => $vs_id) + $vip); } foreach ($plan['ports'] as $port) { usePreparedDeleteBlade('VSPorts', array('vs_id' => $vs_id, 'proto' => $port['proto'], 'vport' => $port['vport'])); usePreparedInsertBlade('VSPorts', array('vs_id' => $vs_id) + $port); } // create triplets foreach ($plan['triplets'] as $triplet) { $tr_key = array('vs_id' => $triplet['vs_id'], 'object_id' => $triplet['object_id'], 'rspool_id' => $triplet['rspool_id']); foreach ($triplet['ports'] as $port) { addSLBPortLink($tr_key + $port); } foreach ($triplet['vips'] as $vip) { addSLBIPLink($tr_key + $vip); } } // update configs usePreparedUpdateBlade('VS', $plan['properties'], array('id' => $vs_id)); // replace tags global $taglist; $chain = array(); foreach ($tag_ids as $tid) { if (!isset($taglist[$tid])) { $dbxlink->rollback(); showError("Unknown tag id {$tid}"); } else { $chain[] = $taglist[$tid]; } } rebuildTagChainForEntity('ipvs', $vs_id, $chain, TRUE); $dbxlink->commit(); showSuccess("old VS configs were copied to VS group"); return buildRedirectURL(NULL, 'default'); }
$model = rtrim($controller, 's'); $controller .= 'Controller'; $dispatch = new $controller($model, $controllerName, $action); if ((int) method_exists($controller, $action)) { call_user_func_array(array($dispatch, $action), $queryString); } else { /* Error Generation Code Here */ } } /** Autoload any classes that are required **/ function __autoload($className) { if (file_exists(ROOT . DS . 'library' . DS . strtolower($className) . '.class.php')) { require_once ROOT . DS . 'library' . DS . strtolower($className) . '.class.php'; } else { if (file_exists(ROOT . DS . 'application' . DS . 'controllers' . DS . strtolower($className) . '.php')) { require_once ROOT . DS . 'application' . DS . 'controllers' . DS . strtolower($className) . '.php'; } else { if (file_exists(ROOT . DS . 'application' . DS . 'models' . DS . strtolower($className) . '.php')) { require_once ROOT . DS . 'application' . DS . 'models' . DS . strtolower($className) . '.php'; } else { /* Error Generation Code Here */ } } } } setReporting(); removeMagicQuotes(); unregisterGlobals(); callHook();
function getIPv6AddressNetworkId($ip_bin, $masklen = 128) { if ($row = callHook('fetchIPv6AddressNetworkRow', $ip_bin, $masklen)) { return $row['id']; } return NULL; }
$admin_account = spotEntity('user', 1); if (isCLIMode() && FALSE !== ($env_user = getenv('USER'))) { // use USER env var if we are in CLI mode $remote_username = $env_user; } else { $remote_username = $admin_account['user_name']; } unset($env_user); unset($admin_account); } $virtual_obj_types = explode(',', getConfigVar('VIRTUAL_OBJ_LISTSRC')); alterConfigWithUserPreferences(); $op = ''; // load additional plugins ob_start(); foreach (glob("{$racktables_plugins_dir}/*.php") as $filename) { require_once $filename; } // display plugins output if it contains something but newlines $tmp = ob_get_clean(); if ($tmp != '' and !preg_match("/^\n+\$/D", $tmp)) { echo $tmp; } unset($tmp); // These will be filled in by fixContext() $expl_tags = array(); $impl_tags = array(); // Initial chain for the current target. $target_given_tags = array(); callHook('initFinished');
function portletRSPoolAddMany($pool_id) { startPortlet('Add many'); printOpFormIntro('addMany'); echo "<table border=0 align=center>\n<tr><td>"; if (getConfigVar('DEFAULT_IPV4_RS_INSERVICE') == 'yes') { printImageHREF('inservice', 'in service'); } else { printImageHREF('notinservice', 'NOT in service'); } echo "</td><td>Format: "; $formats = callHook('getBulkRealsFormats'); printSelect($formats, array('name' => 'format')); echo "</td><td><input type=submit value=Parse></td></tr>\n"; echo "<tr><td colspan=3><textarea name=rawtext cols=100 rows=25></textarea></td></tr>\n"; echo "</table>\n"; finishPortlet(); }
function buildLVSConfig($object_id) { return callHook('buildEntityLVSConfig', spotEntity('object', $object_id)); }
function renderObject8021QSyncSchedule($object, $vswitch, $maxdecisions) { echo '<table border=0 cellspacing=0 cellpadding=3 align=center>'; // FIXME: sort rows newest event last $rows = array(); if (!considerConfiguredConstraint($object, 'SYNC_802Q_LISTSRC')) { $rows['auto sync'] = '<span class="trerror">disabled by operator</span>'; } $rows['last local change'] = datetimestrFromTimestamp($vswitch['last_change']) . ' (' . formatAge($vswitch['last_change']) . ')'; $rows['device out of sync'] = $vswitch['out_of_sync']; if ($vswitch['out_of_sync'] == 'no') { $push_duration = $vswitch['last_push_finished'] - $vswitch['last_push_started']; $rows['last sync session with device'] = datetimestrFromTimestamp($vswitch['last_push_started']) . ' (' . formatAge($vswitch['last_push_started']) . ', ' . ($push_duration < 0 ? 'interrupted' : "lasted {$push_duration}s") . ')'; } if ($vswitch['last_errno']) { $rows['failed'] = datetimestrFromTimestamp($vswitch['last_error_ts']) . ' (' . strerror8021Q($vswitch['last_errno']) . ')'; } if (NULL !== ($new_rows = callHook('alter8021qSyncSummaryItems', $rows))) { $rows = $new_rows; } foreach ($rows as $th => $td) { echo "<tr><th width='50%' class=tdright>{$th}:</th><td class=tdleft colspan=2>{$td}</td></tr>"; } echo '<tr><th class=tdright>run now:</th><td class=tdcenter>'; printOpFormIntro('exec8021QPull'); echo getImageHREF('prev', 'pull remote changes in', TRUE, 101) . '</form></td><td class=tdcenter>'; if ($maxdecisions) { echo getImageHREF('COMMIT gray', 'cannot push due to version conflict(s)'); } else { printOpFormIntro('exec8021QPush'); echo getImageHREF('COMMIT', 'push local changes out', TRUE, 102) . '</form>'; } echo '</td></tr>'; echo '</table>'; }
function renderIPVSConvert($vs_id) { $old_vs_list = callHook('getVSIDsByGroup', $vs_id); $grouped = array(); $used_tags = array(); foreach ($old_vs_list as $old_vs_id) { $vsinfo = spotEntity('ipv4vs', $old_vs_id); foreach ($vsinfo['etags'] as $taginfo) { $used_tags[$taginfo['id']] = $taginfo; } $port_key = $vsinfo['proto'] . '-' . $vsinfo['vport']; $grouped[$port_key][] = $vsinfo; } startPortlet("Found " . count($old_vs_list) . " matching VS"); printOpFormIntro('convert'); if (count($used_tags)) { echo '<p>Assign these tags to VS group:</p>'; foreach ($used_tags as $taginfo) { echo '<p><label><input type=checkbox checked name="taglist[]" value="' . htmlspecialchars($taginfo['id'], ENT_QUOTES) . '""> ' . serializeTags(array($taginfo)) . '<label>'; } } echo '<p>Import settings of these VS:</p>'; echo '<table align=center><tr>'; foreach ($grouped as $port_key => $list) { echo '<th>' . $port_key . '</th>'; } echo '</tr><tr>'; foreach ($grouped as $port_key => $list) { echo '<td><table>'; foreach ($list as $vsinfo) { echo '<tr><td><input type=checkbox name="vs_list[]" checked value="' . htmlspecialchars($vsinfo['id'], ENT_QUOTES) . '"></td><td>'; renderSLBEntityCell($vsinfo); echo '</td></tr>'; } echo '</table></td>'; } echo '</tr></table>'; printImageHREF('next', "Import settings of the selected services", TRUE); echo '</form>'; finishPortlet(); }
function renderObject8021QSync($object_id) { $vswitch = getVLANSwitchInfo($object_id); $object = spotEntity('object', $object_id); try { $R = getRunning8021QConfig($object_id); } catch (Exception $re) { showWarning('Device configuration unavailable:<br>' . $re->getMessage()); return; } $D = getStored8021QConfig($vswitch['object_id'], 'desired'); $C = getStored8021QConfig($vswitch['object_id'], 'cached'); $plan = apply8021QOrder($vswitch['template_id'], get8021QSyncOptions($vswitch, $D, $C, $R['portdata'])); $maxdecisions = 0; foreach ($plan as $port) { if ($port['status'] == 'delete_conflict' or $port['status'] == 'merge_conflict' or $port['status'] == 'add_conflict' or $port['status'] == 'martian_conflict') { $maxdecisions++; } } if (isset($_REQUEST['hl_port_id'])) { assertUIntArg('hl_port_id'); $hl_port_id = intval($_REQUEST['hl_port_id']); $hl_port_name = NULL; addAutoScrollScript("port-{$hl_port_id}"); amplifyCell($object); foreach ($object['ports'] as $port) { if (mb_strlen($port['name']) && $port['id'] == $hl_port_id) { $hl_port_name = $port['name']; break; } } } echo '<table border=0 class=objectview cellspacing=0 cellpadding=0>'; echo '<tr><td class=pcleft width="50%">'; startPortlet('schedule'); echo '<table border=0 cellspacing=0 cellpadding=3 align=center>'; // FIXME: sort rows newest event last $rows = array(); if (!considerConfiguredConstraint($object, 'SYNC_802Q_LISTSRC')) { $rows['auto sync'] = '<span class="trerror">disabled by operator</span>'; } $rows['last local change'] = $vswitch['last_change'] . ' (' . $vswitch['last_change_age'] . ' ago)'; $rows['device out of sync'] = $vswitch['out_of_sync']; if ($vswitch['out_of_sync'] == 'no') { $rows['last sync session with device'] = $vswitch['last_push_finished'] . ' (' . $vswitch['last_push_age'] . ' ago, lasted ' . $vswitch['last_push_lasted'] . ')'; } if ($vswitch['last_errno']) { $rows['failed'] = $vswitch['last_error_ts'] . ' (' . strerror8021Q($vswitch['last_errno']) . ')'; } if (NULL !== ($new_rows = callHook('alter8021qSyncSummaryItems', $rows))) { $rows = $new_rows; } foreach ($rows as $th => $td) { echo "<tr><th width='50%' class=tdright>{$th}:</th><td class=tdleft colspan=2>{$td}</td></tr>"; } echo '<tr><th class=tdright>run now:</th><td class=tdcenter>'; printOpFormIntro('exec8021QPull'); echo getImageHREF('prev', 'pull remote changes in', TRUE, 101) . '</form></td><td class=tdcenter>'; if ($maxdecisions) { echo getImageHREF('COMMIT gray', 'cannot push due to version conflict(s)'); } else { printOpFormIntro('exec8021QPush'); echo getImageHREF('COMMIT', 'push local changes out', TRUE, 102) . '</form>'; } echo '</td></tr>'; echo '</table>'; finishPortlet(); startPortlet('preview legend'); echo '<table cellspacing=0 cellpadding=5 align=center class=widetable>'; echo '<tr><th>status</th><th width="50%">color code</th></tr>'; echo '<tr><td class=tdright>with template role:</td><td class=trbusy> </td></tr>'; echo '<tr><td class=tdright>without template role:</td><td> </td></tr>'; echo '<tr><td class=tdright>new data:</td><td class=trok> </td></tr>'; echo '<tr><td class=tdright>warnings in new data:</td><td class=trwarning> </td></tr>'; echo '<tr><td class=tdright>fatal errors in new data:</td><td class=trerror> </td></tr>'; echo '<tr><td class=tdright>deleted data:</td><td class=trnull> </td></tr>'; echo '</table>'; finishPortlet(); echo '</td><td class=pcright>'; startPortlet('preview/resolve'); switchportInfoJS($object_id); // load JS code to make portnames interactive // initialize one of three popups: we've got data already $port_config = addslashes(json_encode(formatPortConfigHints($object_id, $R))); addJS(<<<END \$(document).ready(function(){ \tvar confData = \$.parseJSON('{$port_config}'); \tapplyConfData(confData); \tvar menuItem = \$('.context-menu-item.itemname-conf'); \tmenuItem.addClass(\$.contextMenu.disabledItemClassName); \tsetItemIcon(menuItem[0], 'ok'); }); END , TRUE); echo '<table cellspacing=0 cellpadding=5 align=center class=widetable width="100%">'; if ($maxdecisions) { echo '<tr><th colspan=2> </th><th colspan=3>discard</th><th> </th></tr>'; } echo '<tr valign=top><th>port</th><th width="40%">last saved version</th>'; if ($maxdecisions) { addJS('js/racktables.js'); printOpFormIntro('resolve8021QConflicts', array('mutex_rev' => $vswitch['mutex_rev'])); foreach (array('left', 'asis', 'right') as $pos) { echo "<th class=tdcenter><input type=radio name=column_radio value={$pos} " . "onclick=\"checkColumnOfRadios('i_', {$maxdecisions}, '_{$pos}')\"></th>"; } } echo '<th width="40%">running version</th></tr>'; $rownum = 0; $plan = sortPortList($plan); $domvlans = array_keys(getDomainVLANs($vswitch['domain_id'])); $default_port = array('mode' => 'access', 'allowed' => array(VLAN_DFL_ID), 'native' => VLAN_DFL_ID); foreach ($plan as $port_name => $item) { $trclass = $left_extra = $right_extra = $left_text = $right_text = ''; $radio_attrs = array(); switch ($item['status']) { case 'ok_to_delete': $left_text = serializeVLANPack($item['left']); $right_text = 'none'; $left_extra = ' trnull'; $right_extra = ' trok'; // no confirmation is necessary break; case 'delete_conflict': $trclass = 'trbusy'; $left_extra = ' trerror'; // can be fixed on request $right_extra = ' trnull'; $left_text = formatVLANPackDiff($item['lastseen'], $item['left']); $right_text = ' '; $radio_attrs = array('left' => '', 'asis' => ' checked', 'right' => ' disabled'); // dummy setting to suppress warnings in resolve8021QConflicts() $item['right'] = $default_port; break; case 'add_conflict': $trclass = 'trbusy'; $right_extra = ' trerror'; $left_text = ' '; $right_text = serializeVLANPack($item['right']); break; case 'ok_to_add': $trclass = 'trbusy'; $right_extra = ' trok'; $left_text = ' '; $right_text = serializeVLANPack($item['right']); break; case 'ok_to_merge': $trclass = 'trbusy'; $left_extra = ' trok'; $right_extra = ' trok'; // fall through // fall through case 'in_sync': $trclass = 'trbusy'; $left_text = $right_text = serializeVLANPack($item['both']); break; case 'ok_to_pull': // at least one of the sides is not in the default state $trclass = 'trbusy'; $right_extra = ' trok'; $left_text = serializeVLANPack($item['left']); $right_text = serializeVLANPack($item['right']); break; case 'ok_to_push': $trclass = ' trbusy'; $left_extra = ' trok'; $left_text = formatVLANPackDiff($C[$port_name], $item['left']); $right_text = serializeVLANPack($item['right']); break; case 'merge_conflict': $trclass = 'trbusy'; $left_extra = ' trerror'; $right_extra = ' trerror'; $left_text = formatVLANPackDiff($C[$port_name], $item['left']); $right_text = serializeVLANPack($item['right']); // enable, but consider each option independently // Don't accept running VLANs not in domain, and // don't offer anything, that VST will deny. // Consider domain and template constraints. $radio_attrs = array('left' => '', 'asis' => ' checked', 'right' => ''); if (!acceptable8021QConfig($item['right']) or count(array_diff($item['right']['allowed'], $domvlans)) or !goodModeForVSTRole($item['right']['mode'], $item['vst_role'])) { $radio_attrs['left'] = ' disabled'; } break; case 'ok_to_push_with_merge': $trclass = 'trbusy'; $left_extra = ' trok'; $right_extra = ' trwarning'; $left_text = formatVLANPackDiff($C[$port_name], $item['left']); $right_text = serializeVLANPack($item['right']); break; case 'none': $left_text = ' '; $right_text = ' '; break; case 'martian_conflict': if ($item['right']['mode'] == 'none') { $right_text = ' '; } else { $right_text = serializeVLANPack($item['right']); $right_extra = ' trerror'; } if ($item['left']['mode'] == 'none') { $left_text = ' '; } else { $left_text = serializeVLANPack($item['left']); $left_extra = ' trerror'; $radio_attrs = array('left' => '', 'asis' => ' checked', 'right' => ' disabled'); // idem, see above $item['right'] = $default_port; } break; default: $trclass = 'trerror'; $left_text = $right_text = 'internal rendering error'; break; } $ancor = ''; $td_class = ''; if (isset($hl_port_name) and $hl_port_name == $port_name) { $ancor = "name='port-{$hl_port_id}'"; $td_class = ' border_highlight'; } echo "<tr class='{$trclass}'><td class='tdleft{$td_class}' NOWRAP><a class='interactive-portname port-menu nolink' {$ancor}>{$port_name}</a></td>"; if (!count($radio_attrs)) { echo "<td class='tdleft{$left_extra}'>{$left_text}</td>"; if ($maxdecisions) { echo '<td> </td><td> </td><td> </td>'; } echo "<td class='tdleft{$right_extra}'>{$right_text}</td>"; } else { echo "<td class='tdleft{$left_extra}'><label for=i_{$rownum}_left>{$left_text}</label></td>"; foreach ($radio_attrs as $pos => $attrs) { echo "<td><input id=i_{$rownum}_{$pos} name=i_{$rownum} type=radio value={$pos}{$attrs}></td>"; } echo "<td class='tdleft{$right_extra}'><label for=i_{$rownum}_right>{$right_text}</label></td>"; } echo '</tr>'; if (count($radio_attrs)) { echo "<input type=hidden name=rm_{$rownum} value=" . $item['right']['mode'] . '>'; echo "<input type=hidden name=rn_{$rownum} value=" . $item['right']['native'] . '>'; foreach ($item['right']['allowed'] as $a) { echo "<input type=hidden name=ra_{$rownum}[] value={$a}>"; } echo "<input type=hidden name=pn_{$rownum} value='" . htmlspecialchars($port_name) . "'>"; } $rownum += count($radio_attrs) ? 1 : 0; } if ($rownum) { echo "<input type=hidden name=nrows value={$rownum}>"; echo '<tr><td colspan=2> </td><td colspan=3 align=center class=tdcenter>'; printImageHREF('UNLOCK', 'resolve conflicts', TRUE); echo '</td><td> </td></tr>'; } echo '</table>'; echo '</form>'; finishPortlet(); echo '</td></tr></table>'; }
function queryTerminal($object_id, $commands, $tolerate_remote_errors = TRUE) { $objectInfo = spotEntity('object', $object_id); $endpoints = findAllEndpoints($object_id, $objectInfo['name']); if (count($endpoints) == 0) { throw new RTGatewayError('no management address set'); } if (count($endpoints) > 1) { throw new RTGatewayError('cannot pick management address'); } // telnet prompt and mode specification switch ($breed = detectDeviceBreed($object_id)) { case 'ios12': case 'fdry5': case 'ftos8': $protocol = 'netcat'; // default is netcat mode $prompt = '^(Login|Username|Password): $|^\\S+[>#]$'; // set the prompt in case user would like to specify telnet protocol break; case 'air12': $protocol = 'telnet'; # Aironet IOS is broken $prompt = '^(Username|Password): $|^\\S+[>#]$'; break; case 'vrp53': case 'vrp55': $protocol = 'telnet'; $prompt = '^\\[[^[\\]]+\\]$|^<[^<>]+>$|^(Username|Password):$|(?:\\[Y\\/N\\]|\\(Y\\/N\\)\\[[YN]\\]):?$'; break; case 'nxos4': $protocol = 'telnet'; $prompt = '(^([Ll]ogin|[Pp]assword):|[>#]) $'; break; case 'xos12': $protocol = 'telnet'; $prompt = ': $|\\.\\d+ # $|\\?\\s*\\([Yy]\\/[Nn]\\)\\s*$'; break; case 'jun10': $protocol = 'telnet'; $prompt = '^login: $|^Password:$|^\\S+@\\S+[>#] $'; break; case 'eos4': $protocol = 'telnet'; # strict RFC854 implementation, netcat won't work $prompt = '^(\\xf2?login|Username|Password): $|^\\S+[>#]$'; break; case 'ros11': $protocol = 'netcat'; # see ftos8 case $prompt = '^(User Name|\\rPassword):$|^\\r?\\S+# $'; break; case 'iosxr4': $protocol = 'telnet'; $prompt = '^\\r?(Login|Username|Password): $|^\\r?\\S+[>#]$'; break; case 'ucs': $protocol = 'ucssdk'; break; default: $protocol = 'netcat'; $prompt = NULL; } // set the default settings before calling user-defined callback $settings = array('hostname' => $endpoints[0], 'protocol' => $protocol, 'port' => NULL, 'prompt' => $prompt, 'username' => NULL, 'password' => NULL, 'timeout' => 15, 'connect_timeout' => 2, 'prompt_delay' => 0.001, 'sudo_user' => NULL, 'identity_file' => NULL); if (is_callable('terminal_settings')) { call_user_func('terminal_settings', $objectInfo, array(&$settings)); } // override settings if (!isset($settings['port']) and $settings['protocol'] == 'netcat') { $settings['port'] = 23; } $params = array($settings['hostname']); $params_from_settings = array(); switch ($settings['protocol']) { case 'telnet': case 'netcat': // prepend command list with vendor-specific disabling pager command switch ($breed) { case 'ios12': $commands = "terminal length 0\n" . $commands; break; case 'nxos4': case 'air12': case 'ftos8': $commands = "terminal length 0\nterminal no monitor\n" . $commands; break; case 'xos12': $commands = "disable clipaging\n" . $commands; break; case 'vrp55': $commands = "screen-length 0 temporary\n" . $commands; break; case 'fdry5': $commands = "skip-page-display\n" . $commands; break; case 'jun10': $commands = "set cli screen-length 0\n" . $commands; break; case 'eos4': $commands = "enable\nno terminal monitor\nterminal length 0\n" . $commands; break; case 'ros11': $commands = "terminal datadump\n" . $commands; $commands .= "\n\n"; # temporary workaround for telnet server break; case 'iosxr4': $commands = "terminal length 0\nterminal monitor disable\n" . $commands; break; case 'dlink': $commands = "disable clipaging\n" . $commands; break; } // prepend telnet commands by credentials if (isset($settings['password'])) { $commands = $settings['password'] . "\n" . $commands; } if (isset($settings['username'])) { $commands = $settings['username'] . "\n" . $commands; } // command-line options are specific to client: telnet or netcat switch ($settings['protocol']) { case 'telnet': $params_from_settings['port'] = 'port'; $params_from_settings['prompt'] = 'prompt'; $params_from_settings['connect-timeout'] = 'connect_timeout'; $params_from_settings['timeout'] = 'timeout'; $params_from_settings['prompt-delay'] = 'prompt_delay'; break; case 'netcat': $params_from_settings['p'] = 'port'; $params_from_settings['w'] = 'timeout'; $params_from_settings['b'] = 'ncbin'; break; } break; case 'ssh': $params_from_settings['port'] = 'port'; $params_from_settings['proto'] = 'proto'; $params_from_settings['username'] = '******'; $params_from_settings['i'] = 'identity_file'; $params_from_settings['sudo-user'] = '******'; $params_from_settings['connect-timeout'] = 'connect_timeout'; break; case 'ucssdk': # remote XML through a Python backend $params = array(); # reset # UCS in its current implementation besides the terminal_settings() provides # an additional username/password feed through the HTML from. Whenever the # user provides the credentials through the form, use these instead of the # credentials [supposedly] set by terminal_settings(). if ($script_mode != TRUE && !isCheckSet('use_terminal_settings')) { genericAssertion('ucs_login', 'string'); genericAssertion('ucs_password', 'string'); $settings['username'] = $_REQUEST['ucs_login']; $settings['password'] = $_REQUEST['ucs_password']; } foreach (array('hostname', 'username', 'password') as $item) { if (empty($settings[$item])) { throw new RTGatewayError("{$item} not available, check terminal_settings()"); } } $commands = "login {$settings['hostname']} {$settings['username']} {$settings['password']}\n" . $commands; break; default: throw RTGatewayError("Invalid terminal protocol '{$settings['protocol']}' specified"); } foreach ($params_from_settings as $param_name => $setting_name) { if (isset($settings[$setting_name])) { if (is_int($param_name)) { $params[] = $settings[$setting_name]; } else { $params[$param_name] = $settings[$setting_name]; } } } callHook('alterTerminalParams', $object_id, $tolerate_remote_errors, array(&$settings['protocol']), array(&$params)); $ret_code = callScript($settings['protocol'], $params, $commands, $out, $errors); if ($settings['protocol'] != 'ssh' || !$tolerate_remote_errors) { if (!empty($errors)) { throw new RTGatewayError("{$settings['protocol']} error: " . rtrim($errors)); } elseif ($ret_code !== 0) { throw new RTGatewayError("{$settings['protocol']} error: result code {$ret_code}"); } } elseif (!empty($errors)) { // ssh and tolerate and non-empty $errors foreach (explode("\n", $errors) as $line) { if (strlen($line)) { showWarning("{$settings['protocol']} {$settings['hostname']}: {$line}"); } } } return strtr($out, array("\r" => "")); // cut ^M symbols }
function queryTerminal($object_id, $commands, $tolerate_remote_errors = TRUE) { $objectInfo = spotEntity('object', $object_id); $endpoints = findAllEndpoints($object_id, $objectInfo['name']); if (count($endpoints) == 0) { throw new RTGatewayError('no management address set'); } if (count($endpoints) > 1) { throw new RTGatewayError('cannot pick management address'); } // telnet prompt and mode specification switch ($breed = detectDeviceBreed($object_id)) { case 'ios12': case 'ftos8': $protocol = 'netcat'; // default is netcat mode $prompt = '^(Login|[Uu]sername|Password): $|^\\S+[>#]$|\\[[^][]*\\]\\? $'; // set the prompt in case user would like to specify telnet protocol $commands = "terminal length 0\nterminal no monitor\n" . $commands; break; case 'air12': $protocol = 'telnet'; # Aironet IOS is broken $prompt = '^(Username|Password): $|^\\S+[>#]$'; $commands = "terminal length 0\nterminal no monitor\n" . $commands; break; case 'fdry5': $protocol = 'netcat'; // default is netcat mode $prompt = '^(Login|Username|Password): $|^\\S+[>#]$'; // set the prompt in case user would like to specify telnet protocol $commands = "skip-page-display\n" . $commands; break; case 'vrp55': case 'vrp85': $commands = "screen-length 0 temporary\n" . $commands; /* fall-through */ /* fall-through */ case 'vrp53': $protocol = 'telnet'; $prompt = '^\\[[^[\\]]+\\]$|^<[^<>]+>$|^(Username|Password):$|\\[[Yy][^\\[\\]]*\\]\\s*:?\\s*$'; break; case 'nxos4': $protocol = 'telnet'; $prompt = '(^([Ll]ogin|[Pp]assword):|[>#]) $'; $commands = "terminal length 0\nterminal no monitor\n" . $commands; break; case 'xos12': $protocol = 'telnet'; $prompt = ': $|\\.\\d+ # $|\\?\\s*\\([Yy]\\/[Nn]\\)\\s*$'; $commands = "disable clipaging\n" . $commands; break; case 'jun10': $protocol = 'telnet'; $prompt = '^login: $|^Password:$|^\\S+@\\S+[>#] $'; $commands = "set cli screen-length 0\n" . $commands; break; case 'eos4': $protocol = 'telnet'; # strict RFC854 implementation, netcat won't work $prompt = '^\\xf2?(login|Username|Password): $|^\\S+[>#]$'; $commands = "enable\nno terminal monitor\nterminal length 0\n" . $commands; break; case 'ros11': $protocol = 'netcat'; # see ftos8 case $prompt = '^(User Name|\\rPassword):$|^\\r?\\S+# $'; $commands = "terminal datadump\n" . $commands; $commands .= "\n\n"; # temporary workaround for telnet server break; case 'iosxr4': $protocol = 'telnet'; $prompt = '^\\r?(Login|Username|Password): $|^\\r?\\S+[>#]$'; $commands = "terminal length 0\nterminal monitor disable\n" . $commands; break; case 'ucs': $protocol = 'ucssdk'; break; case 'dlink': $protocol = 'netcat'; $commands = "disable clipaging\n" . $commands; break; } if (!isset($protocol)) { $protocol = 'netcat'; } if (!isset($prompt)) { $prompt = NULL; } // set the default settings before calling user-defined callback $settings = array('hostname' => $endpoints[0], 'protocol' => $protocol, 'port' => NULL, 'prompt' => $prompt, 'username' => NULL, 'password' => NULL, 'timeout' => 15, 'connect_timeout' => 2, 'prompt_delay' => 0.001, 'sudo_user' => NULL, 'identity_file' => NULL); // override default settings if (is_callable('terminal_settings')) { call_user_func('terminal_settings', $objectInfo, array(&$settings)); } // make gateway-specific CLI params out of settings $params = callHook('makeGatewayParams', $object_id, $tolerate_remote_errors, array(&$settings), array(&$commands)); // call gateway $ret_code = callScript($settings['protocol'], $params, $commands, $out, $errors); if ($settings['protocol'] != 'ssh' || !$tolerate_remote_errors) { if (!empty($errors)) { throw new RTGatewayError("{$settings['protocol']} error: " . rtrim($errors)); } elseif ($ret_code !== 0) { throw new RTGatewayError("{$settings['protocol']} error: result code {$ret_code}"); } } elseif (!empty($errors)) { // ssh and tolerate and non-empty $errors foreach (explode("\n", $errors) as $line) { if (strlen($line)) { showWarning("{$settings['protocol']} {$settings['hostname']}: {$line}"); } } } return strtr($out, array("\r" => "")); // cut ^M symbols }
function renderRSPoolServerForm($pool_id) { global $nextorder; $poolInfo = spotEntity('ipv4rspool', $pool_id); if ($poolInfo['rscount']) { startPortlet("Manage RS list ({$poolInfo['rscount']})"); echo "<table cellspacing=0 cellpadding=5 align=center class=cooltable>\n"; echo "<tr><th> </th><th>Address</th><th>Port</th><th>Comment</th><th>in service</th><th>configuration</th><th> </th></tr>\n"; // new RS form printOpFormIntro('addRS'); echo "<tr class=row_odd valign=top><td>"; printImageHREF('add', 'Add new real server'); echo "</td><td><input type=text name=rsip></td>"; $default_port = getConfigVar('DEFAULT_SLB_RS_PORT'); if ($default_port == 0) { $default_port = ''; } echo "<td><input type=text name=rsport size=5 value='{$default_port}'></td>"; echo "<td><input type=text name=comment size=15></td>"; $checked = getConfigVar('DEFAULT_IPV4_RS_INSERVICE') == 'yes' ? 'checked' : ''; echo "<td><input type=checkbox name=inservice {$checked}></td>"; echo "<td><textarea name=rsconfig></textarea></td><td>"; printImageHREF('ADD', 'Add new real server', TRUE); echo "</td></tr></form>\n"; $order = 'even'; foreach (getRSListInPool($pool_id) as $rsid => $rs) { printOpFormIntro('updRS', array('rs_id' => $rsid)); echo "<tr valign=top class=row_{$order}><td><a href='" . makeHrefProcess(array('op' => 'delRS', 'pool_id' => $pool_id, 'id' => $rsid)) . "'>"; printImageHREF('delete', 'Delete this real server'); echo "</td><td><input type=text name=rsip value='{$rs['rsip']}'></td>"; echo "<td><input type=text name=rsport size=5 value='{$rs['rsport']}'></td>"; echo "<td><input type=text name=comment size=15 value='{$rs['comment']}'></td>"; $checked = $rs['inservice'] == 'yes' ? 'checked' : ''; echo "<td><input type=checkbox name=inservice {$checked}></td>"; echo "<td><textarea name=rsconfig>{$rs['rsconfig']}</textarea></td><td>"; printImageHREF('SAVE', 'Save changes', TRUE); echo "</td></tr></form>\n"; $order = $nextorder[$order]; } echo "</table>\n"; finishPortlet(); } startPortlet('Add many'); printOpFormIntro('addMany'); echo "<table border=0 align=center>\n<tr><td>"; if (getConfigVar('DEFAULT_IPV4_RS_INSERVICE') == 'yes') { printImageHREF('inservice', 'in service'); } else { printImageHREF('notinservice', 'NOT in service'); } echo "</td><td>Format: "; $formats = callHook('getBulkRealsFormats'); printSelect($formats, array('name' => 'format')); echo "</td><td><input type=submit value=Parse></td></tr>\n"; echo "<tr><td colspan=3><textarea name=rawtext cols=100 rows=25></textarea></td></tr>\n"; echo "</table>\n"; finishPortlet(); }
function exec8021QDeploy($object_id, $do_push) { global $dbxlink; $nsaved = $npushed = $nsaved_uplinks = 0; $dbxlink->beginTransaction(); if (NULL === ($vswitch = getVLANSwitchInfo($object_id, 'FOR UPDATE'))) { throw new InvalidArgException('object_id', $object_id, 'VLAN domain is not set for this object'); } $D = getStored8021QConfig($vswitch['object_id'], 'desired'); $C = getStored8021QConfig($vswitch['object_id'], 'cached'); try { $R = getRunning8021QConfig($vswitch['object_id']); } catch (RTGatewayError $e) { usePreparedExecuteBlade('UPDATE VLANSwitch SET last_errno=?, last_error_ts=NOW() WHERE object_id=?', array(E_8021Q_PULL_REMOTE_ERROR, $vswitch['object_id'])); $dbxlink->commit(); return 0; } $conflict = FALSE; $ok_to_push = array(); foreach (get8021QSyncOptions($vswitch, $D, $C, $R['portdata']) as $pn => $port) { // always update cache with new data from switch switch ($port['status']) { case 'ok_to_merge': // FIXME: this can be logged upd8021QPort('cached', $vswitch['object_id'], $pn, $port['both']); break; case 'ok_to_delete': del8021QPort($vswitch['object_id'], $pn); $nsaved++; break; case 'ok_to_add': add8021QPort($vswitch['object_id'], $pn, $port['right']); $nsaved++; break; case 'delete_conflict': case 'merge_conflict': case 'add_conflict': case 'martian_conflict': $conflict = TRUE; break; case 'ok_to_pull': // FIXME: this can be logged upd8021QPort('desired', $vswitch['object_id'], $pn, $port['right']); upd8021QPort('cached', $vswitch['object_id'], $pn, $port['right']); $nsaved++; break; case 'ok_to_push_with_merge': upd8021QPort('cached', $vswitch['object_id'], $pn, $port['right']); // fall through // fall through case 'ok_to_push': $ok_to_push[$pn] = $port['left']; break; } } // redo uplinks unconditionally $domain_vlanlist = getDomainVLANs($vswitch['domain_id']); $Dnew = apply8021QOrder($vswitch['template_id'], getStored8021QConfig($vswitch['object_id'], 'desired')); // Take new "desired" configuration and derive uplink port configuration // from it. Then cancel changes to immune VLANs and save resulting // changes (if any left). $new_uplinks = filter8021QChangeRequests($domain_vlanlist, $Dnew, produceUplinkPorts($domain_vlanlist, $Dnew, $vswitch['object_id'])); $nsaved_uplinks += replace8021QPorts('desired', $vswitch['object_id'], $Dnew, $new_uplinks); if ($nsaved + $nsaved_uplinks) { // saved configuration has changed (either "user" ports have changed, // or uplinks, or both), so bump revision number up) touchVLANSwitch($vswitch['object_id']); } if ($conflict) { usePreparedExecuteBlade('UPDATE VLANSwitch SET out_of_sync="yes", last_errno=?, last_error_ts=NOW() WHERE object_id=?', array(E_8021Q_VERSION_CONFLICT, $vswitch['object_id'])); } else { usePreparedExecuteBlade('UPDATE VLANSwitch SET last_errno=?, last_error_ts=NOW() WHERE object_id=?', array(E_8021Q_NOERROR, $vswitch['object_id'])); // Modified uplinks are very likely to differ from those in R-copy, // so don't mark device as clean, if this happened. This can cost // us an additional, empty round of sync, but at least out_of_sync // won't be mistakenly set to 'no'. // FIXME: A cleaner way of coupling pull and push operations would // be to split this function into two. if (!count($ok_to_push) and !$nsaved_uplinks) { usePreparedExecuteBlade('UPDATE VLANSwitch SET out_of_sync="no" WHERE object_id=?', array($vswitch['object_id'])); } elseif ($do_push) { usePreparedExecuteBlade('UPDATE VLANSwitch SET last_push_started=NOW() WHERE object_id=?', array($vswitch['object_id'])); try { $vlan_names = isset($R['vlannames']) ? $R['vlannames'] : array(); $npushed += exportSwitch8021QConfig($vswitch, $R['vlanlist'], $R['portdata'], $ok_to_push, $vlan_names); // update cache for ports deployed replace8021QPorts('cached', $vswitch['object_id'], $R['portdata'], $ok_to_push); usePreparedExecuteBlade('UPDATE VLANSwitch SET last_push_finished=NOW(), out_of_sync="no", last_errno=? WHERE object_id=?', array(E_8021Q_NOERROR, $vswitch['object_id'])); } catch (RTGatewayError $r) { usePreparedExecuteBlade('UPDATE VLANSwitch SET out_of_sync="yes", last_error_ts=NOW(), last_errno=? WHERE object_id=?', array(E_8021Q_PUSH_REMOTE_ERROR, $vswitch['object_id'])); callHook('pushErrorHandler', $object_id, $r); } } } $dbxlink->commit(); // start downlink work only after unlocking current object to make deadlocks less likely to happen // TODO: only process changed uplink ports if ($nsaved_uplinks) { initiateUplinksReverb($vswitch['object_id'], $new_uplinks); } return $nsaved + $npushed + $nsaved_uplinks; }