Exemplo n.º 1
0
function update8021QPortList()
{
    genericAssertion('ports', 'array');
    $enabled = $disabled = 0;
    global $sic;
    $default_port = array('mode' => 'access', 'allowed' => array(VLAN_DFL_ID), 'native' => VLAN_DFL_ID);
    foreach ($sic['ports'] as $line) {
        if (preg_match('/^enable (.+)$/', $line, $m)) {
            $enabled += add8021QPort(getBypassValue(), $m[1], $default_port);
        } elseif (preg_match('/^disable (.+)$/', $line, $m)) {
            $disabled += del8021QPort(getBypassValue(), $m[1]);
        } else {
            throw new InvalidRequestArgException('ports[]', $line, 'malformed array item');
        }
    }
    # $enabled + $disabled > 0
    if ($enabled) {
        showSuccess("enabled 802.1Q for {$enabled} port(s)");
    }
    if ($disabled) {
        showSuccess("disabled 802.1Q for {$disabled} port(s)");
    }
}
Exemplo n.º 2
0
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;
}