Mapping Neutron network for VPP renderer
[groupbasedpolicy.git] / neutron-vpp-mapper / src / main / java / org / opendaylight / groupbasedpolicy / neutron / vpp / mapper / processors / NetworkAware.java
1 /*\r
2  * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.\r
3  *\r
4  * This program and the accompanying materials are made available under the\r
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
6  * and is available at http://www.eclipse.org/legal/epl-v10.html\r
7  */\r
8 \r
9 package org.opendaylight.groupbasedpolicy.neutron.vpp.mapper.processors;\r
10 \r
11 import java.util.ArrayList;\r
12 import java.util.List;\r
13 \r
14 import org.opendaylight.controller.md.sal.binding.api.DataBroker;\r
15 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;\r
16 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;\r
17 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;\r
18 import org.opendaylight.groupbasedpolicy.util.DataStoreHelper;\r
19 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.Config;\r
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.FlatNetwork;\r
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.NetworkTypeBase;\r
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.VlanNetwork;\r
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.BridgeDomain;\r
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.BridgeDomainBuilder;\r
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.BridgeDomainKey;\r
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.bridge.domain.PhysicalLocationRef;\r
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.bridge.domain.PhysicalLocationRefBuilder;\r
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId;\r
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.NetworkTypeFlat;\r
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.NetworkTypeVlan;\r
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.Networks;\r
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.networks.Network;\r
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.provider.ext.rev150712.NetworkProviderExtension;\r
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;\r
35 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;\r
36 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;\r
37 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;\r
38 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;\r
39 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;\r
40 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;\r
41 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;\r
42 import org.slf4j.Logger;\r
43 import org.slf4j.LoggerFactory;\r
44 \r
45 import com.google.common.annotations.VisibleForTesting;\r
46 import com.google.common.base.Function;\r
47 import com.google.common.base.Optional;\r
48 import com.google.common.collect.Lists;\r
49 \r
50 public class NetworkAware implements MappingProvider<Network> {\r
51 \r
52     private static final Logger LOG = LoggerFactory.getLogger(NetworkAware.class);\r
53 \r
54     private final DataBroker dataBroker;\r
55 \r
56     public NetworkAware(DataBroker dataBroker) {\r
57         this.dataBroker = dataBroker;\r
58     }\r
59 \r
60     @Override\r
61     public InstanceIdentifier<Network> getNeutronDtoIid() {\r
62         return InstanceIdentifier.builder(Neutron.class).child(Networks.class).child(Network.class).build();\r
63     }\r
64 \r
65     @Override\r
66     public void processCreatedNeutronDto(Network network) {\r
67         BridgeDomain bridgeDomain = createBridgeDomain(network);\r
68         if (bridgeDomain != null) {\r
69             ReadWriteTransaction rwTx = dataBroker.newReadWriteTransaction();\r
70             rwTx.put(LogicalDatastoreType.CONFIGURATION, getBridgeDomainIid(bridgeDomain.getId()), bridgeDomain);\r
71             DataStoreHelper.submitToDs(rwTx);\r
72         }\r
73     }\r
74 \r
75     @VisibleForTesting\r
76     BridgeDomain createBridgeDomain(Network network) {\r
77         BridgeDomainBuilder bridgeDomainBuilder = new BridgeDomainBuilder();\r
78         String description = (network.getName() != null) ? network.getName() : "Neutron network";\r
79         bridgeDomainBuilder.setDescription(description);\r
80         bridgeDomainBuilder.setId(network.getUuid().getValue());\r
81         NetworkProviderExtension providerAug = network.getAugmentation(NetworkProviderExtension.class);\r
82         if (providerAug == null || providerAug.getNetworkType() == null) {\r
83             LOG.error("Cannot create VPP bridge domain. Network type not specified in neutron network: {}", network);\r
84             return null;\r
85         }\r
86         bridgeDomainBuilder.setPhysicalLocationRef(resolveDomainLocations(providerAug));\r
87         bridgeDomainBuilder.setType(convertNetworkType(providerAug.getNetworkType()));\r
88         if (providerAug.getNetworkType().isAssignableFrom(NetworkTypeVlan.class)\r
89                 && providerAug.getSegmentationId() != null) {\r
90             try {\r
91                 bridgeDomainBuilder.setVlan(new VlanId(Integer.valueOf(providerAug.getSegmentationId())));\r
92             } catch (NumberFormatException e) {\r
93                 LOG.error("Neutron network {}. Cannot create VLAN ID from segmentation-id: {}. {}",\r
94                         providerAug.getSegmentationId(), network.getUuid(), e);\r
95                 return null;\r
96             }\r
97         }\r
98         return bridgeDomainBuilder.build();\r
99     }\r
100 \r
101     @VisibleForTesting\r
102     List<PhysicalLocationRef> resolveDomainLocations(NetworkProviderExtension providerAug) {\r
103         List<PhysicalLocationRef> locationRefs = new ArrayList<>();\r
104         ReadOnlyTransaction rTx = dataBroker.newReadOnlyTransaction();\r
105         if (providerAug.getPhysicalNetwork() == null) {\r
106             return null;\r
107         }\r
108         Optional<Topology> readTopology = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,\r
109                 getTopologyIid(new TopologyId(providerAug.getPhysicalNetwork())), rTx);\r
110         if (readTopology.isPresent()) {\r
111             Topology topology = readTopology.get();\r
112             for (Node node : topology.getNode()) {\r
113                 PhysicalLocationRefBuilder location = new PhysicalLocationRefBuilder();\r
114                 location.setNodeId(node.getNodeId());\r
115                 location.setInterface(Lists.transform(node.getTerminationPoint(),\r
116                         new Function<TerminationPoint, String>() {\r
117 \r
118                             @Override\r
119                             public String apply(TerminationPoint input) {\r
120                                 return input.getTpId().getValue();\r
121                             }\r
122                         }));\r
123                 locationRefs.add(location.build());\r
124             }\r
125         }\r
126         return locationRefs;\r
127     }\r
128 \r
129     public static Class<? extends NetworkTypeBase> convertNetworkType(\r
130             Class<? extends org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.NetworkTypeBase> base) {\r
131         if (base.isAssignableFrom(NetworkTypeFlat.class)) {\r
132             return FlatNetwork.class;\r
133         }\r
134         if (base.isAssignableFrom(NetworkTypeVlan.class)) {\r
135             return VlanNetwork.class;\r
136         }\r
137         throw new IllegalStateException("Unsupported network type: " + base);\r
138     }\r
139 \r
140     InstanceIdentifier<Topology> getTopologyIid(TopologyId topologyId) {\r
141         return InstanceIdentifier.builder(NetworkTopology.class)\r
142             .child(Topology.class, new TopologyKey(topologyId))\r
143             .build();\r
144     }\r
145 \r
146     InstanceIdentifier<BridgeDomain> getBridgeDomainIid(String id) {\r
147         return InstanceIdentifier.builder(Config.class).child(BridgeDomain.class, new BridgeDomainKey(id)).build();\r
148     }\r
149 \r
150     @Override\r
151     public void processUpdatedNeutronDto(Network originalNetwork, Network updatedNetwork) {\r
152         InstanceIdentifier<BridgeDomain> bdId = getBridgeDomainIid(originalNetwork.getUuid().getValue());\r
153         ReadWriteTransaction rwTx = dataBroker.newReadWriteTransaction();\r
154         rwTx.delete(LogicalDatastoreType.CONFIGURATION, bdId);\r
155         rwTx.put(LogicalDatastoreType.CONFIGURATION, bdId, createBridgeDomain(updatedNetwork));\r
156         DataStoreHelper.submitToDs(rwTx);\r
157     }\r
158 \r
159     @Override\r
160     public void processDeletedNeutronDto(Network network) {\r
161         InstanceIdentifier<BridgeDomain> bdId = getBridgeDomainIid(network.getUuid().getValue());\r
162         ReadWriteTransaction rwTx = dataBroker.newReadWriteTransaction();\r
163         rwTx.delete(LogicalDatastoreType.CONFIGURATION, bdId);\r
164         DataStoreHelper.submitToDs(rwTx);\r
165     }\r
166 }\r