[ONOS-6191] NET L3VPN create operation support

Change-Id: I0ddbf88cae67fdaa0087551dd4b4d066dd3d6c22
diff --git a/apps/l3vpn/netl3vpn/src/main/java/org/onosproject/l3vpn/netl3vpn/impl/InsConstructionUtil.java b/apps/l3vpn/netl3vpn/src/main/java/org/onosproject/l3vpn/netl3vpn/impl/InsConstructionUtil.java
new file mode 100644
index 0000000..d5ea1a6
--- /dev/null
+++ b/apps/l3vpn/netl3vpn/src/main/java/org/onosproject/l3vpn/netl3vpn/impl/InsConstructionUtil.java
@@ -0,0 +1,240 @@
+/*
+ * Copyright 2017-present 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.l3vpn.netl3vpn.impl;
+
+import org.onosproject.l3vpn.netl3vpn.FullMeshVpnConfig;
+import org.onosproject.l3vpn.netl3vpn.HubSpokeVpnConfig;
+import org.onosproject.l3vpn.netl3vpn.VpnInstance;
+import org.onosproject.l3vpn.netl3vpn.VpnSiteRole;
+import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.bgp.l3vpn.rev20160909.ietfbgpl3vpn.devices.device.networkinstances.networkinstance.AugmentedNiNetworkInstance;
+import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.bgp.l3vpn.rev20160909.ietfbgpl3vpn.devices.device.networkinstances.networkinstance.DefaultAugmentedNiNetworkInstance;
+import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.bgp.l3vpn.rev20160909.ietfbgpl3vpn.devices.device.networkinstances.networkinstance.augmentedninetworkinstance.DefaultL3Vpn;
+import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.bgp.l3vpn.rev20160909.ietfbgpl3vpn.devices.device.networkinstances.networkinstance.augmentedninetworkinstance.L3Vpn;
+import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.bgp.l3vpn.rev20160909.ietfbgpl3vpn.l3vpnvrfparams.DefaultIpv4;
+import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.bgp.l3vpn.rev20160909.ietfbgpl3vpn.l3vpnvrfparams.DefaultIpv6;
+import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.bgp.l3vpn.rev20160909.ietfbgpl3vpn.l3vpnvrfparams.Ipv4;
+import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.bgp.l3vpn.rev20160909.ietfbgpl3vpn.l3vpnvrfparams.Ipv6;
+import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.bgp.l3vpn.rev20160909.ietfbgpl3vpn.l3vpnvrfparams.ipv4.DefaultUnicast;
+import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.bgp.l3vpn.rev20160909.ietfbgpl3vpn.l3vpnvrfparams.ipv4.Unicast;
+import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.bgp.l3vpn.rev20160909.ietfbgpl3vpn.routedistinguisherparams.DefaultRouteDistinguisher;
+import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.bgp.l3vpn.rev20160909.ietfbgpl3vpn.routedistinguisherparams.RouteDistinguisher;
+import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.bgp.l3vpn.rev20160909.ietfbgpl3vpn.routetargetparams.DefaultRouteTargets;
+import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.bgp.l3vpn.rev20160909.ietfbgpl3vpn.routetargetparams.RouteTargets;
+import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.bgp.l3vpn.rev20160909.ietfbgpl3vpn.routetargetparams.routetargets.Config;
+import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.bgp.l3vpn.rev20160909.ietfbgpl3vpn.routetargetparams.routetargets.DefaultConfig;
+import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.bgp.l3vpn.rev20160909.ietfbgpl3vpn.routetargetset.DefaultRts;
+import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.bgp.l3vpn.rev20160909.ietfbgpl3vpn.routetargetset.Rts;
+import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.bgp.l3vpn.rev20160909.ietfbgpl3vpn.routetargetset.rts.RtTypeEnum;
+import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.l3vpn.svc.rev20160730.ietfl3vpnsvc.siteattachmentipconnection.IpConnection;
+import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.instance.rev20160623.ietfnetworkinstance.devices.device.DefaultNetworkInstances;
+import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.instance.rev20160623.ietfnetworkinstance.devices.device.NetworkInstances;
+import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.instance.rev20160623.ietfnetworkinstance.devices.device.networkinstances.DefaultNetworkInstance;
+import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.instance.rev20160623.ietfnetworkinstance.devices.device.networkinstances.NetworkInstance;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import static org.onosproject.l3vpn.netl3vpn.VpnType.ANY_TO_ANY;
+import static org.onosproject.l3vpn.netl3vpn.VpnType.HUB;
+import static org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.bgp.l3vpn.rev20160909.ietfbgpl3vpn.routetargetset.rts.RtTypeEnum.BOTH;
+import static org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.bgp.l3vpn.rev20160909.ietfbgpl3vpn.routetargetset.rts.RtTypeEnum.EXPORT;
+import static org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.bgp.l3vpn.rev20160909.ietfbgpl3vpn.routetargetset.rts.RtTypeEnum.IMPORT;
+
+/**
+ * Representation of utility for instance creation and deletion.
+ */
+public final class InsConstructionUtil {
+
+    // No instantiation.
+    private InsConstructionUtil() {
+    }
+
+    /**
+     * Creates network instance with augmented info such as RD and RT.
+     *
+     * @param vpnIns  VPN instance
+     * @param role    VPN role
+     * @param connect ip connection
+     * @return network instance
+     */
+    public static NetworkInstances createInstance(VpnInstance vpnIns,
+                                                  VpnSiteRole role,
+                                                  IpConnection connect) {
+        NetworkInstance ins = new DefaultNetworkInstance();
+        NetworkInstances instances = new DefaultNetworkInstances();
+        List<NetworkInstance> insList = new LinkedList<>();
+
+        L3Vpn l3Vpn = buildRd(vpnIns);
+        DefaultAugmentedNiNetworkInstance augIns =
+                buildRt(connect, role, l3Vpn, vpnIns);
+        ins.name(vpnIns.vpnName());
+        insList.add(ins);
+        ((DefaultNetworkInstance) ins).addAugmentation(augIns);
+        instances.networkInstance(insList);
+        return instances;
+    }
+
+    /**
+     * Builds RT from l3 VPN according to the address family VPN belongs to.
+     * It returns built aug network instance from l3 VPN.
+     *
+     * @param con   ip connection
+     * @param role  site VPN role
+     * @param l3Vpn l3 VPN
+     * @param ins   VPN instance
+     * @return aug network instance
+     */
+    private static DefaultAugmentedNiNetworkInstance buildRt(IpConnection con,
+                                                             VpnSiteRole role,
+                                                             L3Vpn l3Vpn,
+                                                             VpnInstance ins) {
+        Ipv4 ipv4 = null;
+        Ipv6 ipv6 = null;
+        if (con.ipv4() != null && con.ipv4().addresses()
+                .providerAddress() != null) {
+            ipv4 = buildIpv4Rt(role, ins);
+        }
+        if (con.ipv6() != null && con.ipv6()
+                .addresses().providerAddress() != null) {
+            ipv6 = buildIpv6Rt(role, ins);
+        }
+        l3Vpn.ipv4(ipv4);
+        l3Vpn.ipv6(ipv6);
+
+        AugmentedNiNetworkInstance augInst =
+                new DefaultAugmentedNiNetworkInstance();
+        augInst.l3Vpn(l3Vpn);
+        return (DefaultAugmentedNiNetworkInstance) augInst;
+    }
+
+    /**
+     * Builds ipv6 RT in the device model.
+     *
+     * @param role   site VPN role
+     * @param vpnIns VPN instance
+     * @return ipv6
+     */
+    private static Ipv6 buildIpv6Rt(VpnSiteRole role, VpnInstance vpnIns) {
+        RouteTargets rts6 = new DefaultRouteTargets();
+        Ipv6 v6 = new DefaultIpv6();
+        org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.bgp.l3vpn
+                .rev20160909.ietfbgpl3vpn.l3vpnvrfparams.ipv6.Unicast uni6 =
+                new org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang
+                        .ietf.bgp.l3vpn.rev20160909.ietfbgpl3vpn.l3vpnvrfparams
+                        .ipv6.DefaultUnicast();
+
+        Config configV6 = configRouteTarget(vpnIns, role);
+        rts6.config(configV6);
+        uni6.routeTargets(rts6);
+        v6.unicast(uni6);
+        return v6;
+    }
+
+    /**
+     * Builds ipv4 RT in the device model.
+     *
+     * @param role   site VPN role
+     * @param vpnIns VPN instance
+     * @return ipv4
+     */
+    private static Ipv4 buildIpv4Rt(VpnSiteRole role, VpnInstance vpnIns) {
+        RouteTargets rts4 = new DefaultRouteTargets();
+        Unicast uni4 = new DefaultUnicast();
+        Ipv4 v4 = new DefaultIpv4();
+
+        Config configV4 = configRouteTarget(vpnIns, role);
+        rts4.config(configV4);
+        uni4.routeTargets(rts4);
+        v4.unicast(uni4);
+        return v4;
+    }
+
+    /**
+     * Configures route target according to the site VPN role from the stored
+     * VPN instance.
+     *
+     * @param ins  VPN instance
+     * @param role site VPN role
+     * @return route target config
+     */
+    private static Config configRouteTarget(VpnInstance ins,
+                                            VpnSiteRole role) {
+        Rts rts1;
+        Config config = new DefaultConfig();
+        List<Rts> rtsList = new LinkedList<>();
+
+        if (ins.type() == ANY_TO_ANY) {
+            String rtVal = ((FullMeshVpnConfig) ins.vpnConfig()).rt();
+            rts1 = getRtsVal(rtVal, BOTH);
+        } else {
+            String rtVal1;
+            String rtVal2;
+            HubSpokeVpnConfig conf = (HubSpokeVpnConfig) ins.vpnConfig();
+            if (role.role() == HUB) {
+                rtVal1 = conf.hubImpRt();
+                rtVal2 = conf.hubExpRt();
+            } else {
+                rtVal1 = conf.spokeImpRt();
+                rtVal2 = conf.spokeExpRt();
+            }
+            rts1 = getRtsVal(rtVal1, IMPORT);
+            Rts rts2 = getRtsVal(rtVal2, EXPORT);
+            rtsList.add(rts2);
+        }
+        rtsList.add(rts1);
+        config.rts(rtsList);
+        return config;
+    }
+
+    /**
+     * Returns the device model RT from the RT type and RT value after
+     * building it.
+     *
+     * @param rtVal RT value
+     * @param type  RT type
+     * @return device model RT
+     */
+    private static Rts getRtsVal(String rtVal, RtTypeEnum type) {
+        Rts rts = new DefaultRts();
+        rts.rt(rtVal);
+        rts.rtType(type);
+        return rts;
+    }
+
+    /**
+     * Builds RD from the stored device model VPN instance.
+     *
+     * @param vpn VPN instance
+     * @return l3 VPN object
+     */
+    private static L3Vpn buildRd(VpnInstance vpn) {
+
+        String rd = vpn.vpnConfig().rd();
+        org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.bgp.l3vpn
+                .rev20160909.ietfbgpl3vpn.routedistinguisherparams
+                .routedistinguisher.Config config = new org.onosproject.yang
+                .gen.v1.urn.ietf.params.xml.ns.yang.ietf.bgp.l3vpn.rev20160909
+                .ietfbgpl3vpn.routedistinguisherparams.routedistinguisher
+                .DefaultConfig();
+        config.rd(rd);
+        RouteDistinguisher dist = new DefaultRouteDistinguisher();
+        dist.config(config);
+        L3Vpn l3vpn = new DefaultL3Vpn();
+        l3vpn.routeDistinguisher(dist);
+        return l3vpn;
+    }
+}