OvsdbControllerConfig.java 4.36 KB
/*
 * Copyright 2015 Open Networking Laboratory
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.onosproject.driver.ovsdb;

import org.onlab.packet.IpAddress;
import org.onlab.packet.TpPort;
import org.onosproject.net.AnnotationKeys;
import org.onosproject.net.DeviceId;
import org.onosproject.net.behaviour.ControllerConfig;
import org.onosproject.net.behaviour.ControllerInfo;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.driver.AbstractHandlerBehaviour;
import org.onosproject.net.driver.DriverHandler;
import org.onosproject.ovsdb.controller.OvsdbBridge;
import org.onosproject.ovsdb.controller.OvsdbClientService;
import org.onosproject.ovsdb.controller.OvsdbController;
import org.onosproject.ovsdb.controller.OvsdbNodeId;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import static com.google.common.base.Preconditions.checkState;
import static org.onlab.util.Tools.delay;

/**
 * Implementation of controller config which allows to get and set controllers.
 */
public class OvsdbControllerConfig extends AbstractHandlerBehaviour implements ControllerConfig {
    @Override
    public List<ControllerInfo> getControllers() {
        DriverHandler handler = handler();
        OvsdbClientService clientService = getOvsdbClientService(handler);
        Set<ControllerInfo> controllers = clientService.getControllers(
                handler().data().deviceId());
        return new ArrayList<>(controllers);
    }

    @Override
    public void setControllers(List<ControllerInfo> controllers) {
        DriverHandler handler = handler();
        OvsdbClientService clientService = getOvsdbClientService(handler);
        if (!clientService.getControllers(handler().data().deviceId())
                .equals(controllers)) {
            clientService.setControllersWithDeviceId(handler().
                    data().deviceId(), controllers);
        }
    }

    // Used for getting OvsdbClientService.
    private OvsdbClientService getOvsdbClientService(DriverHandler handler) {
        OvsdbController ovsController = handler.get(OvsdbController.class);
        DeviceService deviceService = handler.get(DeviceService.class);
        DeviceId ofDeviceId = handler.data().deviceId();
        String[] mgmtAddress = deviceService.getDevice(ofDeviceId)
                .annotations().value(AnnotationKeys.MANAGEMENT_ADDRESS).split(":");
        String targetIp = mgmtAddress[0];
        TpPort targetPort = null;
        if (mgmtAddress.length > 1) {
            targetPort = TpPort.tpPort(Integer.parseInt(mgmtAddress[1]));
        }

        List<OvsdbNodeId> nodeIds = ovsController.getNodeIds().stream()
                .filter(nodeId -> nodeId.getIpAddress().equals(targetIp))
                .collect(Collectors.toList());
        if (nodeIds.size() == 0) {
            //TODO decide what port?
            ovsController.connect(IpAddress.valueOf(targetIp),
                                  targetPort == null ? TpPort.tpPort(6640) : targetPort);
            delay(1000); //FIXME... connect is async
        }
        List<OvsdbClientService> clientServices = ovsController.getNodeIds().stream()
                .filter(nodeId -> nodeId.getIpAddress().equals(targetIp))
                .map(ovsController::getOvsdbClient)
                .filter(cs -> cs.getBridges().stream().anyMatch(b -> dpidMatches(b, ofDeviceId)))
                .collect(Collectors.toList());
        checkState(clientServices.size() > 0, "No clientServices found");
        //FIXME add connection to management address if null --> done ?
        return clientServices.size() > 0 ? clientServices.get(0) : null;
    }

    private static boolean dpidMatches(OvsdbBridge bridge, DeviceId deviceId) {
        String bridgeDpid = "of:" + bridge.datapathId().value();
        String ofDpid = deviceId.toString();
        return bridgeDpid.equals(ofDpid);
    }
}