2 * Copyright (c) 2016, 2017 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.netvirt.neutronvpn;
10 import com.google.common.base.Optional;
11 import com.google.common.util.concurrent.ListenableFuture;
13 import java.util.ArrayList;
14 import java.util.List;
16 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
17 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
18 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
19 import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
20 import org.opendaylight.genius.datastoreutils.DataStoreJobCoordinator;
21 import org.opendaylight.genius.mdsalutil.MDSALUtil;
22 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.networkmaps.NetworkMap;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.networkmaps.NetworkMapBuilder;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.networkmaps.NetworkMapKey;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.networks.Network;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.Subnets;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet;
30 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
31 import org.slf4j.Logger;
32 import org.slf4j.LoggerFactory;
34 public class NeutronSubnetChangeListener extends AsyncDataTreeChangeListenerBase<Subnet, NeutronSubnetChangeListener>
35 implements AutoCloseable {
36 private static final Logger LOG = LoggerFactory.getLogger(NeutronSubnetChangeListener.class);
37 private final DataBroker dataBroker;
38 private final NeutronvpnManager nvpnManager;
39 private final NeutronvpnNatManager nvpnNatManager;
40 private final NeutronExternalSubnetHandler externalSubnetHandler;
42 public NeutronSubnetChangeListener(final DataBroker dataBroker, final NeutronvpnManager neutronvpnManager,
43 final NeutronvpnNatManager neutronvpnNatMgr, final NeutronExternalSubnetHandler externalSubnetHandler) {
44 super(Subnet.class, NeutronSubnetChangeListener.class);
45 this.dataBroker = dataBroker;
46 this.nvpnManager = neutronvpnManager;
47 this.nvpnNatManager = neutronvpnNatMgr;
48 this.externalSubnetHandler = externalSubnetHandler;
52 LOG.info("{} start", getClass().getSimpleName());
53 registerListener(LogicalDatastoreType.CONFIGURATION, dataBroker);
57 protected InstanceIdentifier<Subnet> getWildCardPath() {
58 return InstanceIdentifier.create(Neutron.class).child(Subnets.class).child(Subnet.class);
62 protected NeutronSubnetChangeListener getDataTreeChangeListener() {
63 return NeutronSubnetChangeListener.this;
68 protected void add(InstanceIdentifier<Subnet> identifier, Subnet input) {
69 LOG.trace("Adding Subnet : key: {}, value={}", identifier, input);
70 Uuid networkId = input.getNetworkId();
71 Uuid subnetId = input.getUuid();
72 Network network = NeutronvpnUtils.getNeutronNetwork(dataBroker, networkId);
73 if (network == null || !NeutronvpnUtils.isNetworkTypeSupported(network)) {
74 //FIXME: This should be removed when support for VLAN and GRE network types is added
75 LOG.error("neutron vpn doesn't support vlan/gre network provider type for the port {} "
76 + "which is part of network {}."
77 + " Skipping the processing of Subnet add DCN", input.getName(), network);
81 NeutronvpnUtils.addToSubnetCache(input);
82 final DataStoreJobCoordinator subnetDataStoreCoordinator = DataStoreJobCoordinator.getInstance();
83 subnetDataStoreCoordinator.enqueueJob("SUBNET- " + subnetId.getValue(), () -> {
84 WriteTransaction writeConfigTxn = dataBroker.newWriteOnlyTransaction();
85 handleNeutronSubnetCreated(input.getUuid(), String.valueOf(input.getCidr().getValue()), networkId,
87 externalSubnetHandler.handleExternalSubnetAdded(network, subnetId, null, writeConfigTxn);
89 List<ListenableFuture<Void>> futures = new ArrayList<>();
90 futures.add(writeConfigTxn.submit());
96 protected void remove(InstanceIdentifier<Subnet> identifier, Subnet input) {
97 LOG.trace("Removing subnet : key: {}, value={}", identifier, input);
98 Uuid networkId = input.getNetworkId();
99 Uuid subnetId = input.getUuid();
100 Network network = NeutronvpnUtils.getNeutronNetwork(dataBroker, networkId);
101 if (network == null || !NeutronvpnUtils.isNetworkTypeSupported(network)) {
102 //FIXME: This should be removed when support for GRE network types is added
103 LOG.error("neutron vpn doesn't support gre network provider type for the port {} "
104 + "which is part of network {}."
105 + " Skipping the processing of Subnet remove DCN", input.getName(), network);
109 NeutronvpnUtils.removeFromSubnetCache(input);
110 final DataStoreJobCoordinator subnetDataStoreCoordinator = DataStoreJobCoordinator.getInstance();
111 subnetDataStoreCoordinator.enqueueJob("SUBNET- " + subnetId.getValue(), () -> {
112 WriteTransaction writeConfigTxn = dataBroker.newWriteOnlyTransaction();
113 handleNeutronSubnetDeleted(input.getUuid(), networkId, null);
114 externalSubnetHandler.handleExternalSubnetRemoved(network, subnetId, writeConfigTxn);
116 List<ListenableFuture<Void>> futures = new ArrayList<>();
117 futures.add(writeConfigTxn.submit());
123 protected void update(InstanceIdentifier<Subnet> identifier, Subnet original, Subnet update) {
124 LOG.trace("Updating Subnet : key: {}, original value={}, update value={}", identifier, original, update);
125 Uuid networkId = update.getNetworkId();
126 Uuid subnetId = update.getUuid();
127 Network network = NeutronvpnUtils.getNeutronNetwork(dataBroker, networkId);
128 if (network == null || !NeutronvpnUtils.isNetworkTypeSupported(network)) {
129 LOG.error("neutron vpn doesn't support vlan/gre network provider type for the port {} "
130 + "which is part of network {}."
131 + " Skipping the processing of Subnet update DCN", update.getName(), network);
135 final DataStoreJobCoordinator portDataStoreCoordinator = DataStoreJobCoordinator.getInstance();
136 portDataStoreCoordinator.enqueueJob("SUBNET- " + subnetId.getValue(), () -> {
137 WriteTransaction writeConfigTxn = dataBroker.newWriteOnlyTransaction();
138 handleNeutronSubnetUpdated(subnetId, network, update.getTenantId());
139 externalSubnetHandler.handleExternalSubnetUpdated(network, subnetId, null, writeConfigTxn);
140 NeutronvpnUtils.addToSubnetCache(update);
142 List<ListenableFuture<Void>> futures = new ArrayList<>();
143 futures.add(writeConfigTxn.submit());
148 private void handleNeutronSubnetCreated(Uuid subnetId, String subnetIp, Uuid networkId, Uuid tenantId) {
149 nvpnManager.updateSubnetNode(subnetId, subnetIp, tenantId, networkId, null/*routerID*/, null/*vpnID*/);
150 if (networkId != null) {
151 createSubnetToNetworkMapping(subnetId, networkId);
155 private void handleNeutronSubnetDeleted(Uuid subnetId, Uuid networkId, Uuid tenantId) {
156 Uuid vpnId = NeutronvpnUtils.getVpnForNetwork(dataBroker, networkId);
158 nvpnManager.removeSubnetFromVpn(vpnId, subnetId);
160 if (networkId != null) {
161 deleteSubnetToNetworkMapping(subnetId, networkId);
163 nvpnManager.deleteSubnetMapNode(subnetId);
166 private void handleNeutronSubnetUpdated(Uuid subnetId, Network network, Uuid tenantId) {
167 Uuid oldNetworkId = NeutronvpnUtils.getSubnetmap(dataBroker, subnetId).getNetworkId();
168 Uuid networkId = network.getUuid();
169 if (oldNetworkId != null && !oldNetworkId.equals(networkId)) {
170 deleteSubnetToNetworkMapping(subnetId, oldNetworkId);
172 if (networkId != null && !networkId.equals(oldNetworkId)) {
173 createSubnetToNetworkMapping(subnetId, networkId);
176 nvpnManager.updateSubnetNode(subnetId, null, tenantId, networkId, null/*routerID*/, null/*vpnID*/);
179 // TODO Clean up the exception handling
180 @SuppressWarnings("checkstyle:IllegalCatch")
181 private void createSubnetToNetworkMapping(Uuid subnetId, Uuid networkId) {
183 InstanceIdentifier networkMapIdentifier = NeutronvpnUtils.buildNetworkMapIdentifier(networkId);
184 Optional<NetworkMap> optionalNetworkMap =
185 NeutronvpnUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION, networkMapIdentifier);
186 NetworkMapBuilder nwMapBuilder = null;
187 if (optionalNetworkMap.isPresent()) {
188 nwMapBuilder = new NetworkMapBuilder(optionalNetworkMap.get());
190 nwMapBuilder = new NetworkMapBuilder().setKey(new NetworkMapKey(networkId)).setNetworkId(networkId);
191 LOG.debug("Adding a new network node in NetworkMaps DS for network {}", networkId.getValue());
193 List<Uuid> subnetIdList = nwMapBuilder.getSubnetIdList();
194 if (subnetIdList == null) {
195 subnetIdList = new ArrayList<>();
197 subnetIdList.add(subnetId);
198 nwMapBuilder.setSubnetIdList(subnetIdList);
199 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
200 networkMapIdentifier, nwMapBuilder.build());
201 LOG.debug("Created subnet-network mapping for subnet {} network {}", subnetId.getValue(),
202 networkId.getValue());
203 } catch (Exception e) {
204 LOG.error("Create subnet-network mapping failed for subnet {} network {}", subnetId.getValue(),
205 networkId.getValue());
209 // TODO Clean up the exception handling
210 @SuppressWarnings("checkstyle:IllegalCatch")
211 private void deleteSubnetToNetworkMapping(Uuid subnetId, Uuid networkId) {
213 InstanceIdentifier networkMapIdentifier = NeutronvpnUtils.buildNetworkMapIdentifier(networkId);
214 Optional<NetworkMap> optionalNetworkMap =
215 NeutronvpnUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION, networkMapIdentifier);
216 if (optionalNetworkMap.isPresent()) {
217 NetworkMapBuilder nwMapBuilder = new NetworkMapBuilder(optionalNetworkMap.get());
218 List<Uuid> subnetIdList = nwMapBuilder.getSubnetIdList();
219 if (subnetIdList.remove(subnetId)) {
220 if (subnetIdList.size() == 0) {
221 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, networkMapIdentifier);
222 LOG.debug("Deleted network node in NetworkMaps DS for network {}", subnetId.getValue(),
223 networkId.getValue());
225 nwMapBuilder.setSubnetIdList(subnetIdList);
226 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, networkMapIdentifier,
227 nwMapBuilder.build());
228 LOG.debug("Deleted subnet-network mapping for subnet {} network {}", subnetId.getValue(),
229 networkId.getValue());
232 LOG.error("Subnet {} is not mapped to network {}", subnetId.getValue(), networkId.getValue());
235 LOG.error("network {} not present for subnet {} ", networkId, subnetId);
237 } catch (Exception e) {
238 LOG.error("Delete subnet-network mapping failed for subnet {} network {}", subnetId.getValue(),
239 networkId.getValue());