function resolve8021QConflicts() { global $sic, $dbxlink; assertUIntArg('mutex_rev', TRUE); // counts from 0 assertUIntArg('nrows'); // Divide submitted radio buttons into 3 groups: // left (saved version wins) // asis (ignore) // right (running version wins) $F = array(); for ($i = 0; $i < $sic['nrows']; $i++) { if (!array_key_exists("i_{$i}", $sic)) { continue; } // let's hope other inputs are in place switch ($sic["i_{$i}"]) { case 'left': case 'right': $F[$sic["pn_{$i}"]] = array('mode' => $sic["rm_{$i}"], 'allowed' => array_fetch($sic, "ra_{$i}", array()), 'native' => $sic["rn_{$i}"], 'decision' => $sic["i_{$i}"]); break; default: // don't care } } $dbxlink->beginTransaction(); try { if (NULL === ($vswitch = getVLANSwitchInfo($sic['object_id'], 'FOR UPDATE'))) { throw new InvalidArgException('object_id', $sic['object_id'], 'VLAN domain is not set for this object'); } if ($vswitch['mutex_rev'] != $sic['mutex_rev']) { throw new InvalidRequestArgException('mutex_rev', $sic['mutex_rev'], 'expired form (table data has changed)'); } $D = getStored8021QConfig($vswitch['object_id'], 'desired'); $C = getStored8021QConfig($vswitch['object_id'], 'cached'); $R = getRunning8021QConfig($vswitch['object_id']); $plan = get8021QSyncOptions($vswitch, $D, $C, $R['portdata']); $ndone = 0; foreach ($F as $port_name => $port) { if (!array_key_exists($port_name, $plan)) { continue; } elseif ($plan[$port_name]['status'] == 'merge_conflict') { // for R neither mutex nor revisions can be emulated, but revision change can be if (!same8021QConfigs($port, $R['portdata'][$port_name])) { throw new InvalidRequestArgException("port {$port_name}", '(hidden)', 'expired form (switch data has changed)'); } if ($port['decision'] == 'right') { // D wins, frame R by writing value of R to C $ndone += upd8021QPort('cached', $vswitch['object_id'], $port_name, $port); } elseif ($port['decision'] == 'left') { // R wins, cross D up $ndone += upd8021QPort('cached', $vswitch['object_id'], $port_name, $D[$port_name]); } // otherwise there was no decision made } elseif ($plan[$port_name]['status'] == 'delete_conflict' or $plan[$port_name]['status'] == 'martian_conflict') { if ($port['decision'] == 'left') { // confirm deletion of local copy $ndone += del8021QPort($vswitch['object_id'], $port_name); } } // otherwise ignore a decision that doesn't address a conflict } } catch (InvalidRequestArgException $e) { $dbxlink->rollBack(); showFuncMessage(__FUNCTION__, 'ERR1'); return; } catch (Exception $e) { $dbxlink->rollBack(); showFuncMessage(__FUNCTION__, 'ERR2'); return; } $dbxlink->commit(); showFuncMessage(__FUNCTION__, 'OK', array($ndone)); }
function formatVLANPackDiff($old, $current) { $ret = ''; $new_pack = serializeVLANPack($current); $new_size = substr_count($new_pack, ','); if (!same8021QConfigs($old, $current)) { $old_pack = serializeVLANPack($old); $old_size = substr_count($old_pack, ','); $ret .= '<s>' . $old_pack . '</s><br>'; // make diff $added = groupIntsToRanges(array_diff($current['allowed'], $old['allowed'])); $removed = groupIntsToRanges(array_diff($old['allowed'], $current['allowed'])); if ($old['mode'] == $current['mode'] && $current['mode'] == 'trunk') { if (!empty($added)) { $ret .= '<span class="vlan-diff diff-add">+ ' . implode(', ', $added) . '</span><br>'; } if (!empty($removed)) { $ret .= '<span class="vlan-diff diff-rem">- ' . implode(', ', $removed) . '</span><br>'; } } } $ret .= $new_pack; return $ret; }
function replace8021QPorts($instance = 'desired', $object_id, $before, $changes) { $done = 0; foreach ($changes as $port_name => $port) { if (!array_key_exists($port_name, $before) or !same8021QConfigs($port, $before[$port_name])) { upd8021QPort($instance, $object_id, $port_name, $port); $done++; } } return $done; }
function queueChangesToSwitch($switch_id, $order, $before, $check_only = FALSE) { global $script_mode; $ret = array(); $nsaved = 0; foreach ($order as $portname => $portorder) { if (!same8021QConfigs($portorder, $before[$portname])) { if ($script_mode) { $object = spotEntity('object', $switch_id); print $object['name'] . " {$portname}: " . serializeVLANPack($before[$portname]) . ' -> ' . serializeVLANPack($portorder) . "\n"; } if (!$check_only) { upd8021QPort('desired', $switch_id, $portname, $portorder); $nsaved++; } } } if (!$check_only && $nsaved) { touchVLANSwitch($switch_id); } return $nsaved; }