com.mirantis.opendaylight.route.RouteBuilderServiceImpl.java Source code

Java tutorial

Introduction

Here is the source code for com.mirantis.opendaylight.route.RouteBuilderServiceImpl.java

Source

/**
 * Copyright 2015 Leonid Bogdanov
 *
 * 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 com.mirantis.opendaylight.route;

import static com.google.common.base.Functions.constant;
import static com.google.common.util.concurrent.Futures.immediateFuture;
import static com.google.common.util.concurrent.Futures.transform;
import static com.mirantis.opendaylight.Utils.ROUTE_LIST_ID;
import static com.mirantis.opendaylight.Utils.toNodeID;
import static com.mirantis.opendaylight.Utils.toTpID;
import static org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType.CONFIGURATION;

import java.util.Objects;
import java.util.UUID;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;

import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
import org.opendaylight.controller.md.sal.common.api.data.OptimisticLockFailedException;
import org.opendaylight.yang.gen.v1.urn.com.mirantis.opendaylight.rev150505.*;
import org.opendaylight.yang.gen.v1.urn.com.mirantis.opendaylight.rev150505.route.list.Route;
import org.opendaylight.yang.gen.v1.urn.com.mirantis.opendaylight.rev150505.route.list.RouteBuilder;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Counter32;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;
import org.opendaylight.yangtools.yang.common.RpcResult;
import org.opendaylight.yangtools.yang.common.RpcResultBuilder;

import com.google.common.base.Optional;
import com.google.common.util.concurrent.ListenableFuture;
import com.mirantis.opendaylight.Retrier;

/**
 * @author Leonid Bogdanov
 */
public final class RouteBuilderServiceImpl implements RouteBuilderService {
    private final DataBroker dataBroker;
    private final ExecutorService executor;

    public RouteBuilderServiceImpl(DataBroker dataBroker, ExecutorService executor) {
        this.dataBroker = dataBroker;
        this.executor = executor;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Future<RpcResult<AddRouteOutput>> addRoute(AddRouteInput input) {
        try {
            String[] src = input.getSrc().split(":", 2);
            String[] dst = input.getDst().split(":", 2);
            Uri srcNode = new Uri(toNodeID(src[0]));
            Uri srcTp = new Uri(toTpID(src[0], src[1]));
            Uri dstNode = new Uri(toNodeID(dst[0]));
            Uri dstTp = new Uri(toTpID(dst[0], dst[1]));

            return Retrier.<RpcResult<AddRouteOutput>>create().using(executor)
                    .when(e -> e instanceof OptimisticLockFailedException).code(() -> {
                        ReadWriteTransaction tx = dataBroker.newReadWriteTransaction();
                        ListenableFuture<Short> vlanF = allocateVlan(tx, srcNode, dstNode);
                        ListenableFuture<Route> routeF = transform(vlanF, (Short vlan) -> {
                            Route route = new RouteBuilder().setId(new Uuid(UUID.randomUUID().toString()))
                                    .setSrcNode(srcNode).setSrcTp(srcTp).setDstNode(dstNode).setDstTp(dstTp)
                                    .setVlan(vlan).build();
                            tx.put(CONFIGURATION, ROUTE_LIST_ID, route, true);
                            return route;
                        }, executor);
                        return transform(routeF, (Route route) -> {
                            AddRouteOutput output = new AddRouteOutputBuilder().setId(route.getId()).build();
                            RpcResult<AddRouteOutput> result = RpcResultBuilder.success(output).build();
                            return transform(tx.submit(), constant(result));
                        }, executor);
                    }).retry();
        } catch (RuntimeException e) {
            RpcResult<AddRouteOutput> result = RpcResultBuilder.<AddRouteOutput>failed()
                    .withError(ErrorType.APPLICATION, e.getMessage(), e).build();
            return immediateFuture(result);
        }
    }

    private ListenableFuture<Short> allocateVlan(ReadWriteTransaction tx, Uri srcNode, Uri dstNode) {
        if (Objects.equals(srcNode, dstNode)) {
            return immediateFuture(null);
        }
        InstanceIdentifier<VlanCounter> counterId = InstanceIdentifier.create(VlanCounter.class);
        return transform(tx.read(CONFIGURATION, counterId), (Optional<VlanCounter> counter) -> {
            short curVal = counter.transform(cnt -> cnt.getNextVlan().getValue()).or(1L).shortValue();
            Counter32 nextVal = new Counter32(curVal < 4094 ? curVal + 1L : 1L);
            tx.put(CONFIGURATION, counterId, new VlanCounterBuilder().setNextVlan(nextVal).build());
            return curVal;
        }, executor);
    }
}