org.opendaylight.faas.fabric.general.FabricManagementAPIProvider.java Source code

Java tutorial

Introduction

Here is the source code for org.opendaylight.faas.fabric.general.FabricManagementAPIProvider.java

Source

/**
 * Copyright (c) 2015 Huawei Technologies Co. Ltd. and others. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
 * and is available at http://www.eclipse.org/legal/epl-v10.html
 */
package org.opendaylight.faas.fabric.general;

import com.google.common.base.Optional;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.google.common.util.concurrent.AsyncFunction;
import com.google.common.util.concurrent.CheckedFuture;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.SettableFuture;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ExecutionException;
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.ReadOnlyTransaction;
import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.RpcRegistration;
import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
import org.opendaylight.faas.fabric.general.spi.FabricRenderer;
import org.opendaylight.faas.fabric.general.spi.FabricRendererFactory;
import org.opendaylight.faas.fabric.utils.MdSalUtils;
import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.fabric.capable.device.rev150930.FabricCapableDevice;
import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.fabric.rev150930.AddLinkToFabricInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.fabric.rev150930.AddNodeToFabricInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.fabric.rev150930.ComposeFabricInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.fabric.rev150930.ComposeFabricInputBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.fabric.rev150930.ComposeFabricOutput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.fabric.rev150930.ComposeFabricOutputBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.fabric.rev150930.DecomposeFabricInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.fabric.rev150930.FabricId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.fabric.rev150930.FabricNode;
import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.fabric.rev150930.FabricNodeBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.fabric.rev150930.FabricService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.fabric.rev150930.GetAllFabricsOutput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.fabric.rev150930.GetAllFabricsOutputBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.fabric.rev150930.GetPortsFromFabricInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.fabric.rev150930.GetPortsFromFabricOutput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.fabric.rev150930.RmLinkFromFabricInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.fabric.rev150930.RmNodeFromFabricInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.fabric.rev150930.fabric.attributes.DeviceLinks;
import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.fabric.rev150930.fabric.attributes.DeviceLinksBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.fabric.rev150930.fabric.attributes.DeviceLinksKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.fabric.rev150930.fabric.attributes.DeviceNodes;
import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.fabric.rev150930.fabric.attributes.DeviceNodesBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.fabric.rev150930.fabric.attributes.DeviceNodesKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.fabric.rev150930.fabric.attributes.OptionsBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.fabric.rev150930.network.topology.topology.node.FabricAttribute;
import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.fabric.rev150930.network.topology.topology.node.FabricAttributeBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.fabric.type.rev150930.DeviceRole;
import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.fabric.type.rev150930.LinkRef;
import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.fabric.type.rev150930.NodeRef;
import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.fabric.type.rev150930.ServiceCapabilities;
import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.fabric.type.rev150930.VlanFabric;
import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.fabric.type.rev150930.VxlanFabric;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.fabric.impl.rev150930.FabricsSetting;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.fabric.impl.rev150930.FabricsSettingBuilder;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.node.attributes.SupportingNode;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.node.attributes.SupportingNodeBuilder;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.node.attributes.SupportingNodeKey;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.opendaylight.yangtools.yang.common.RpcResult;
import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class FabricManagementAPIProvider implements AutoCloseable, FabricService {

    private static final Logger LOG = LoggerFactory.getLogger(FabricManagementAPIProvider.class);

    private final DataBroker dataBroker;
    private final RpcProviderRegistry rpcRegistry;

    private RpcRegistration<FabricService> rpcRegistration;

    private final FabricRendererRegistry rendererMgr;

    private final ExecutorService executor;

    public FabricManagementAPIProvider(final DataBroker dataBroker, final RpcProviderRegistry rpcRegistry,
            ExecutorService executor, FabricRendererRegistry rendererMgr) {

        this.dataBroker = dataBroker;
        this.rpcRegistry = rpcRegistry;

        this.executor = executor;

        this.rendererMgr = rendererMgr;

    }

    public void start() {
        rpcRegistration = rpcRegistry.addRpcImplementation(FabricService.class, this);
    }

    @Override
    public void close() throws Exception {
        if (rpcRegistration != null) {
            rpcRegistration.close();
        }
    }

    @Override
    public Future<RpcResult<Void>> decomposeFabric(DecomposeFabricInput input) {
        final RpcResult<Void> result = RpcResultBuilder.<Void>success().build();

        if (input == null) {
            return Futures.immediateFailedCheckedFuture(new IllegalArgumentException("fabricId can not be empty!"));
        }
        final FabricId fabricId = input.getFabricId();

        if (fabricId == null) {
            return Futures.immediateFailedCheckedFuture(new IllegalArgumentException("fabricId can not be empty!"));
        }

        ReadWriteTransaction rt = dataBroker.newReadWriteTransaction();

        final InstanceIdentifier<Node> fabricpath = Constants.DOM_FABRICS_PATH.child(Node.class,
                new NodeKey(fabricId));

        CheckedFuture<Optional<Node>, ReadFailedException> readFuture = rt.read(LogicalDatastoreType.OPERATIONAL,
                fabricpath);

        return Futures.transform(readFuture, (AsyncFunction<Optional<Node>, RpcResult<Void>>) optional -> {

            if (optional.isPresent()) {
                Node fabric = optional.get();
                FabricInstanceCache.INSTANCE.retrieveFabric(fabricId).notifyFabricDeleted(fabric);

                WriteTransaction wt = dataBroker.newWriteOnlyTransaction();
                wt.delete(LogicalDatastoreType.OPERATIONAL, fabricpath);
                wt.delete(LogicalDatastoreType.CONFIGURATION, fabricpath);
                wt.delete(LogicalDatastoreType.OPERATIONAL, MdSalUtils.createTopoIId(fabricId.getValue()));
                MdSalUtils.wrapperSubmit(wt, executor);

                FabricInstanceCache.INSTANCE.removeFabric(fabricId);
            }

            return Futures.immediateFuture(result);
        });
    }

    @Override
    public Future<RpcResult<GetAllFabricsOutput>> getAllFabrics() {

        final SettableFuture<RpcResult<GetAllFabricsOutput>> futureResult = SettableFuture.create();
        final RpcResultBuilder<GetAllFabricsOutput> resultBuilder = RpcResultBuilder.<GetAllFabricsOutput>success();
        final GetAllFabricsOutputBuilder outputBuilder = new GetAllFabricsOutputBuilder();

        ReadOnlyTransaction trans = dataBroker.newReadOnlyTransaction();
        ListenableFuture<Optional<Topology>> readFuture = trans.read(LogicalDatastoreType.OPERATIONAL,
                Constants.DOM_FABRICS_PATH);
        Futures.addCallback(readFuture, new FutureCallback<Optional<Topology>>() {

            @Override
            public void onSuccess(Optional<Topology> result) {
                if (result.isPresent()) {
                    List<Node> nodes = result.get().getNode();
                    List<FabricId> fabricIds = new ArrayList<>();
                    if (nodes != null) {
                        for (Node node : nodes) {
                            FabricNode fnode = node.getAugmentation(FabricNode.class);
                            if (fnode != null) {
                                fabricIds.add(new FabricId(node.getNodeId()));
                            }
                        }
                        outputBuilder.setFabricId(fabricIds);
                    }
                }
                futureResult.set(resultBuilder.withResult(outputBuilder.build()).build());

            }

            @Override
            public void onFailure(Throwable th) {
                LOG.debug("Failed to read network-topology dom", th);
                futureResult.setException(th);
            }
        }, executor);

        return futureResult;
    }

    @Override
    public Future<RpcResult<ComposeFabricOutput>> composeFabric(final ComposeFabricInput input) {
        ComposeFabricInputBuilder inputBuilder = new ComposeFabricInputBuilder(input);
        String msg = null;
        if ((msg = checkFabricOptions(inputBuilder)) != null) {
            return Futures.immediateFailedCheckedFuture(new IllegalArgumentException(msg));
        }

        final FabricId fabricId = new FabricId(String.format("fabric:%d", this.genNextFabricNum()));

        final InstanceIdentifier<Node> fnodepath = MdSalUtils.createFNodeIId(fabricId);
        final InstanceIdentifier<FabricNode> fabricpath = fnodepath.augmentation(FabricNode.class);

        NodeBuilder fnodeBuilder = new NodeBuilder();
        buildNodeAttribute(fnodeBuilder, input, fabricId);

        FabricNodeBuilder fabricBuilder = new FabricNodeBuilder();
        FabricAttributeBuilder attrBuilder = new FabricAttributeBuilder();
        buildFabricAttribute(attrBuilder, inputBuilder);

        FabricRendererFactory rendererFactory = rendererMgr.getFabricRendererFactory(input.getType());
        FabricRenderer renderer = rendererFactory.composeFabric(fabricpath, attrBuilder, input);
        if (renderer == null) {
            return Futures.immediateFailedCheckedFuture(
                    new RuntimeException("Can not compose fabric due the renderer return false."));
        }

        fabricBuilder.setFabricAttribute(attrBuilder.build());
        FabricInstance fabric = FabricInstanceCache.INSTANCE.addFabric(fabricId, input.getType(), renderer);
        fabric.addListener(rendererFactory.createListener(fabricpath, fabricBuilder.getFabricAttribute()));

        final FabricNode fabricNode = fabricBuilder.build();
        fnodeBuilder.addAugmentation(FabricNode.class, fabricNode);

        ReadWriteTransaction trans = dataBroker.newReadWriteTransaction();

        trans.put(LogicalDatastoreType.OPERATIONAL, fnodepath, fnodeBuilder.build(), true);
        trans.put(LogicalDatastoreType.CONFIGURATION, fnodepath, fnodeBuilder.build(), true);
        trans.put(LogicalDatastoreType.OPERATIONAL, MdSalUtils.createTopoIId(fabricId.getValue()),
                MdSalUtils.newTopo(fabricId.getValue()));

        CheckedFuture<Void, TransactionCommitFailedException> future = trans.submit();

        return Futures.transform(future, (AsyncFunction<Void, RpcResult<ComposeFabricOutput>>) submitResult -> {
            RpcResultBuilder<ComposeFabricOutput> resultBuilder = RpcResultBuilder.<ComposeFabricOutput>success();
            ComposeFabricOutputBuilder outputBuilder = new ComposeFabricOutputBuilder();
            outputBuilder.setFabricId(fabricId);

            FabricInstanceCache.INSTANCE.retrieveFabric(fabricId).notifyFabricCreated(fabricNode);
            return Futures.immediateFuture(resultBuilder.withResult(outputBuilder.build()).build());
        });
    }

    private String checkFabricOptions(final ComposeFabricInputBuilder input) {
        List<ServiceCapabilities> capabilities = null;
        if (input.getOptions() != null) {
            capabilities = input.getOptions().getCapabilitySupported();
        }

        if (capabilities == null) {
            capabilities = Lists.newArrayList();
        }
        Set<ServiceCapabilities> allDevCapabilities = Sets.newHashSet();

        List<DeviceNodes> devices = input.getDeviceNodes();
        if (devices == null || devices.isEmpty()) {
            return "No device can support the capability of fabric.";
        }

        ReadOnlyTransaction rt = dataBroker.newReadOnlyTransaction();
        List<CheckedFuture<Optional<FabricCapableDevice>, ReadFailedException>> futures = Lists.newArrayList();
        for (DeviceNodes device : devices) {
            @SuppressWarnings("unchecked")
            InstanceIdentifier<Node> devIid = (InstanceIdentifier<Node>) device.getDeviceRef().getValue();
            CheckedFuture<Optional<FabricCapableDevice>, ReadFailedException> future = rt
                    .read(LogicalDatastoreType.OPERATIONAL, devIid.augmentation(FabricCapableDevice.class));
            futures.add(future);
        }

        try {
            List<Optional<FabricCapableDevice>> capDevices = Futures.allAsList(futures).get();

            for (Optional<FabricCapableDevice> opt : capDevices) {
                if (opt.isPresent()) {
                    FabricCapableDevice capDevice = opt.get();
                    if (capDevice.getCapabilitySupported() != null) {
                        allDevCapabilities.addAll(capDevice.getCapabilitySupported());
                    }
                    if (capDevice.getSupportedFabric() != null) {
                        boolean supported = false;
                        switch (input.getType()) {
                        case VXLAN:
                            supported = capDevice.getSupportedFabric().contains(VxlanFabric.class);
                            break;
                        case VLAN:
                            supported = capDevice.getSupportedFabric().contains(VlanFabric.class);
                            break;
                        default:
                            break;
                        }
                        if (!supported) {
                            return String.format("Device does not support this fabric type.");
                        }
                    } else {
                        return String.format("Device does not support this fabric type.");
                    }
                } else {
                    return String.format("Device is not a fabric capable device.");
                }
            }

            for (ServiceCapabilities cap : capabilities) {
                if (!allDevCapabilities.contains(cap)) {
                    return String.format("No device can support this capability [%s].", cap.name());
                }
            }

            if (capabilities.isEmpty()) {
                OptionsBuilder builder = input.getOptions() == null ? new OptionsBuilder()
                        : new OptionsBuilder(input.getOptions());

                input.setOptions(builder.setCapabilitySupported(Lists.newArrayList(allDevCapabilities)).build());
            }
        } catch (InterruptedException | ExecutionException e) {
            LOG.error("", e);
            return "Exception ocurred when reading DomStore.";
        }
        return null;
    }

    private void buildNodeAttribute(NodeBuilder builder, ComposeFabricInput input, FabricId fabricId) {

        builder.setKey(new NodeKey(fabricId));

        List<DeviceNodes> devices = input.getDeviceNodes();
        if (devices != null) {
            List<SupportingNode> snodes = Lists.newArrayList();
            for (DeviceNodes device : devices) {
                InstanceIdentifier<?> nodeRef = device.getDeviceRef().getValue();
                NodeId nodeid = nodeRef.firstKeyOf(Node.class).getNodeId();
                TopologyId topoId = nodeRef.firstKeyOf(Topology.class).getTopologyId();

                SupportingNodeBuilder snodeBuilder = new SupportingNodeBuilder();
                snodeBuilder.setNodeRef(nodeid);
                snodeBuilder.setTopologyRef(topoId);
                snodeBuilder.setKey(new SupportingNodeKey(nodeid, topoId));
                snodes.add(snodeBuilder.build());
            }
            builder.setSupportingNode(snodes);
        }
    }

    private void buildFabricAttribute(FabricAttributeBuilder builder, ComposeFabricInputBuilder input) {
        builder.setName(input.getName());

        builder.setDescription(input.getDescription());
        builder.setType(input.getType());
        builder.setDeviceLinks(input.getDeviceLinks());
        // remove augment
        builder.setDeviceNodes(getDeviceNodesInput(input.getDeviceNodes()));
        builder.setOptions(input.getOptions());
    }

    private List<DeviceNodes> getDeviceNodesInput(List<DeviceNodes> input) {
        if (input == null) {
            return null;
        }
        List<DeviceNodes> ret = Lists.newArrayList();
        for (DeviceNodes node : input) {
            DeviceNodesBuilder builder = new DeviceNodesBuilder();
            builder.setDeviceRef(node.getDeviceRef());
            builder.setKey(node.getKey());
            builder.setRole(node.getRole());
            ret.add(builder.build());
        }
        return ret;
    }

    private long genNextFabricNum() {
        long ret = 1;

        FabricsSettingBuilder settingBuilder = new FabricsSettingBuilder();
        ReadWriteTransaction trans = dataBroker.newReadWriteTransaction();

        InstanceIdentifier<FabricsSetting> fabricImplPath = InstanceIdentifier.create(FabricsSetting.class);
        ListenableFuture<Optional<FabricsSetting>> readFuture = trans.read(LogicalDatastoreType.CONFIGURATION,
                fabricImplPath);
        Optional<FabricsSetting> optional;
        try {
            optional = readFuture.get();
            if (optional.isPresent()) {
                ret = optional.get().getNextFabricNum();
            }
        } catch (InterruptedException | ExecutionException e) {
            LOG.error("can not read fabric setting", e);
        }

        settingBuilder.setNextFabricNum(ret + 1);
        trans.put(LogicalDatastoreType.CONFIGURATION, fabricImplPath, settingBuilder.build());
        MdSalUtils.wrapperSubmit(trans, executor);

        return ret;
    }

    @Override
    public Future<RpcResult<Void>> rmNodeFromFabric(RmNodeFromFabricInput input) {
        final RpcResult<Void> result = RpcResultBuilder.<Void>success().build();

        FabricId fabricId = input.getFabricId();
        final NodeRef device = input.getNodeRef();

        final FabricInstance fabricObj = FabricInstanceCache.INSTANCE.retrieveFabric(fabricId);
        if (fabricObj == null) {
            return Futures.immediateFailedFuture(new IllegalArgumentException("fabric is not exist!"));
        }

        ReadWriteTransaction trans = dataBroker.newReadWriteTransaction();

        // del fabric attribute
        InstanceIdentifier<DeviceNodes> devicepath = Constants.DOM_FABRICS_PATH
                .child(Node.class, new NodeKey(fabricId)).augmentation(FabricNode.class)
                .child(FabricAttribute.class).child(DeviceNodes.class, new DeviceNodesKey(device));

        trans.delete(LogicalDatastoreType.OPERATIONAL, devicepath);

        // del node attribute
        @SuppressWarnings("unchecked")
        InstanceIdentifier<Node> noderef = (InstanceIdentifier<Node>) device.getValue();
        NodeId deviceid = noderef.firstKeyOf(Node.class).getNodeId();
        TopologyId topoid = noderef.firstKeyOf(Topology.class).getTopologyId();
        InstanceIdentifier<SupportingNode> suplNodeIid = MdSalUtils.createFNodeIId(input.getFabricId())
                .child(SupportingNode.class, new SupportingNodeKey(deviceid, topoid));

        trans.delete(LogicalDatastoreType.OPERATIONAL, suplNodeIid);

        CheckedFuture<Void, TransactionCommitFailedException> future = trans.submit();

        return Futures.transform(future, new AsyncFunction<Void, RpcResult<Void>>() {

            @SuppressWarnings("unchecked")
            @Override
            public ListenableFuture<RpcResult<Void>> apply(Void submitResult) throws Exception {
                fabricObj.notifyDeviceRemoved((InstanceIdentifier<Node>) device.getValue());
                return Futures.immediateFuture(result);
            }
        });
    }

    @Override
    public Future<RpcResult<Void>> addNodeToFabric(AddNodeToFabricInput input) {

        final RpcResult<Void> result = RpcResultBuilder.<Void>success().build();

        final FabricId fabricId = input.getFabricId();
        final NodeRef device = input.getNodeRef();
        final DeviceRole role = input.getRole();

        final InstanceIdentifier<DeviceNodes> path = Constants.DOM_FABRICS_PATH
                .child(Node.class, new NodeKey(fabricId)).augmentation(FabricNode.class)
                .child(FabricAttribute.class).child(DeviceNodes.class, new DeviceNodesKey(device));

        final FabricInstance fabricObj = FabricInstanceCache.INSTANCE.retrieveFabric(fabricId);
        if (fabricObj == null) {
            return Futures.immediateFailedFuture(new IllegalArgumentException("fabric is not exist!"));
        }

        WriteTransaction trans = dataBroker.newWriteOnlyTransaction();
        // set fabric attribute
        DeviceNodesBuilder dnodeBuilder = new DeviceNodesBuilder();
        dnodeBuilder.setKey(new DeviceNodesKey(device)).setDeviceRef(device).build();
        fabricObj.addNodeToFabric(dnodeBuilder, input);
        trans.put(LogicalDatastoreType.OPERATIONAL, path, dnodeBuilder.build(), true);

        // set node attribute
        @SuppressWarnings("unchecked")
        InstanceIdentifier<Node> noderef = (InstanceIdentifier<Node>) device.getValue();
        NodeId deviceid = noderef.firstKeyOf(Node.class).getNodeId();
        TopologyId topoid = noderef.firstKeyOf(Topology.class).getTopologyId();
        final InstanceIdentifier<SupportingNode> suplNodeIid = MdSalUtils.createFNodeIId(input.getFabricId())
                .child(SupportingNode.class, new SupportingNodeKey(deviceid, topoid));
        SupportingNodeBuilder suplNodeBuilder = new SupportingNodeBuilder();
        suplNodeBuilder.setNodeRef(deviceid);
        suplNodeBuilder.setTopologyRef(topoid);
        suplNodeBuilder.setKey(new SupportingNodeKey(deviceid, topoid));
        trans.put(LogicalDatastoreType.OPERATIONAL, suplNodeIid, suplNodeBuilder.build(), true);

        CheckedFuture<Void, TransactionCommitFailedException> future = trans.submit();

        return Futures.transform(future, new AsyncFunction<Void, RpcResult<Void>>() {

            @SuppressWarnings("unchecked")
            @Override
            public ListenableFuture<RpcResult<Void>> apply(Void submitResult) throws Exception {
                fabricObj.notifyDeviceAdded((InstanceIdentifier<Node>) device.getValue(), role);
                return Futures.immediateFuture(result);
            }
        });
    }

    @Override
    public Future<RpcResult<Void>> rmLinkFromFabric(RmLinkFromFabricInput input) {

        final RpcResult<Void> result = RpcResultBuilder.<Void>success().build();

        FabricId fabricId = input.getFabricId();
        LinkRef link = input.getLinkRef();

        InstanceIdentifier<DeviceLinks> devicepath = Constants.DOM_FABRICS_PATH
                .child(Node.class, new NodeKey(fabricId)).augmentation(FabricNode.class)
                .child(FabricAttribute.class).child(DeviceLinks.class, new DeviceLinksKey(link));

        WriteTransaction trans = dataBroker.newWriteOnlyTransaction();

        trans.delete(LogicalDatastoreType.OPERATIONAL, devicepath);

        CheckedFuture<Void, TransactionCommitFailedException> future = trans.submit();

        return Futures.transform(future,
                (AsyncFunction<Void, RpcResult<Void>>) submitResult -> Futures.immediateFuture(result));
    }

    @Override
    public Future<RpcResult<Void>> addLinkToFabric(AddLinkToFabricInput input) {

        final RpcResult<Void> result = RpcResultBuilder.<Void>success().build();

        FabricId fabricId = input.getFabricId();
        LinkRef link = input.getLinkRef();

        final InstanceIdentifier<DeviceLinks> path = Constants.DOM_FABRICS_PATH
                .child(Node.class, new NodeKey(fabricId)).augmentation(FabricNode.class)
                .child(FabricAttribute.class).child(DeviceLinks.class, new DeviceLinksKey(link));

        final FabricInstance fabricObj = FabricInstanceCache.INSTANCE.retrieveFabric(fabricId);
        if (fabricObj == null) {
            return Futures.immediateFailedFuture(new IllegalArgumentException("fabric is not exist!"));
        }

        WriteTransaction trans = dataBroker.newWriteOnlyTransaction();

        DeviceLinksBuilder linkBuilder = new DeviceLinksBuilder();
        linkBuilder.setKey(new DeviceLinksKey(link)).setLinkRef(link).build();

        trans.put(LogicalDatastoreType.OPERATIONAL, path, linkBuilder.build(), false);

        CheckedFuture<Void, TransactionCommitFailedException> future = trans.submit();

        return Futures.transform(future,
                (AsyncFunction<Void, RpcResult<Void>>) submitResult -> Futures.immediateFuture(result));
    }

    @Override
    public Future<RpcResult<GetPortsFromFabricOutput>> getPortsFromFabric(GetPortsFromFabricInput input) {
        // TODO Auto-generated method stub
        return null;
    }
}