7862856261460905082aa9fb6ab3e668a29f66b8
[netvirt.git] / vpnservice / neutronvpn / neutronvpn-impl / src / main / java / org / opendaylight / netvirt / neutronvpn / NeutronSubnetChangeListener.java
1 /*
2  * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.netvirt.neutronvpn;
9
10 import com.google.common.base.Optional;
11 import java.util.ArrayList;
12 import java.util.List;
13 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
14 import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
15 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
16 import org.opendaylight.genius.mdsalutil.MDSALUtil;
17 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
18 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.networkmaps.NetworkMap;
19 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.networkmaps.NetworkMapBuilder;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.networkmaps.NetworkMapKey;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.networks.Network;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.Subnets;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet;
25 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
26 import org.slf4j.Logger;
27 import org.slf4j.LoggerFactory;
28
29 public class NeutronSubnetChangeListener extends AsyncDataTreeChangeListenerBase<Subnet, NeutronSubnetChangeListener>
30         implements AutoCloseable {
31     private static final Logger LOG = LoggerFactory.getLogger(NeutronSubnetChangeListener.class);
32     private final DataBroker dataBroker;
33     private final NeutronvpnManager nvpnManager;
34
35     public NeutronSubnetChangeListener(final DataBroker dataBroker, final NeutronvpnManager nVpnMgr) {
36         super(Subnet.class, NeutronSubnetChangeListener.class);
37         this.dataBroker = dataBroker;
38         nvpnManager = nVpnMgr;
39     }
40
41     public void start() {
42         LOG.info("{} start", getClass().getSimpleName());
43         registerListener(LogicalDatastoreType.CONFIGURATION, dataBroker);
44     }
45
46     @Override
47     protected InstanceIdentifier<Subnet> getWildCardPath() {
48         return InstanceIdentifier.create(Neutron.class).child(Subnets.class).child(Subnet.class);
49     }
50
51     @Override
52     protected NeutronSubnetChangeListener getDataTreeChangeListener() {
53         return NeutronSubnetChangeListener.this;
54     }
55
56
57     @Override
58     protected void add(InstanceIdentifier<Subnet> identifier, Subnet input) {
59         LOG.trace("Adding Subnet : key: {}, value={}", identifier, input);
60         Uuid networkId = input.getNetworkId();
61         Network network = NeutronvpnUtils.getNeutronNetwork(dataBroker, networkId);
62         if (network == null || !NeutronvpnUtils.isNetworkTypeSupported(network)) {
63             //FIXME: This should be removed when support for VLAN and GRE network types is added
64             LOG.error("neutron vpn doesn't support vlan/gre network provider type for the port {} which is part of network {}."
65                     + " Skipping the processing of Subnet add DCN", input.getName(), network);
66             return;
67         }
68         handleNeutronSubnetCreated(input.getUuid(), String.valueOf(input.getCidr().getValue()), networkId,
69                 input.getTenantId());
70         NeutronvpnUtils.addToSubnetCache(input);
71     }
72
73     @Override
74     protected void remove(InstanceIdentifier<Subnet> identifier, Subnet input) {
75         LOG.trace("Removing subnet : key: {}, value={}", identifier, input);
76         Uuid networkId = input.getNetworkId();
77         Network network = NeutronvpnUtils.getNeutronNetwork(dataBroker, networkId);
78         if (network == null || !NeutronvpnUtils.isNetworkTypeSupported(network)) {
79             //FIXME: This should be removed when support for GRE network types is added
80             LOG.error("neutron vpn doesn't support gre network provider type for the port {} which is part of network {}."
81                     + " Skipping the processing of Subnet remove DCN", input.getName(), network);
82             return;
83         }
84         handleNeutronSubnetDeleted(input.getUuid(), networkId, null);
85         NeutronvpnUtils.removeFromSubnetCache(input);
86     }
87
88     @Override
89     protected void update(InstanceIdentifier<Subnet> identifier, Subnet original, Subnet update) {
90         LOG.trace("Updating Subnet : key: {}, original value={}, update value={}", identifier, original, update);
91         Uuid networkId = update.getNetworkId();
92         Network network = NeutronvpnUtils.getNeutronNetwork(dataBroker, networkId);
93         if (network == null || !NeutronvpnUtils.isNetworkTypeSupported(network)) {
94             LOG.error("neutron vpn doesn't support vlan/gre network provider type for the port {} which is part of network {}."
95                     + " Skipping the processing of Subnet update DCN", update.getName(), network);
96             return;
97         }
98         handleNeutronSubnetUpdated(update.getUuid(), networkId, update.getTenantId());
99         NeutronvpnUtils.addToSubnetCache(update);
100     }
101
102     private void handleNeutronSubnetCreated(Uuid subnetId, String subnetIp, Uuid networkId, Uuid tenantId) {
103         nvpnManager.updateSubnetNode(subnetId, subnetIp, tenantId, networkId, null/*routerID*/, null/*vpnID*/);
104         if (networkId != null) {
105             createSubnetToNetworkMapping(subnetId, networkId);
106         }
107     }
108
109     private void handleNeutronSubnetDeleted(Uuid subnetId, Uuid networkId, Uuid tenantId) {
110         Uuid vpnId = NeutronvpnUtils.getVpnForNetwork(dataBroker, networkId);
111         if (vpnId != null) {
112             nvpnManager.removeSubnetFromVpn(vpnId, subnetId);
113         }
114         if (networkId != null)  {
115             deleteSubnetToNetworkMapping(subnetId, networkId);
116         }
117         nvpnManager.deleteSubnetMapNode(subnetId);
118     }
119
120     private void handleNeutronSubnetUpdated(Uuid subnetId, Uuid networkId, Uuid tenantId) {
121         Uuid oldNetworkId = NeutronvpnUtils.getSubnetmap(dataBroker, subnetId).getNetworkId();
122         if (oldNetworkId != null && !oldNetworkId.equals(networkId)) {
123             deleteSubnetToNetworkMapping(subnetId, oldNetworkId);
124         }
125         if (networkId != null && !networkId.equals(oldNetworkId)) {
126             createSubnetToNetworkMapping(subnetId, networkId);
127         }
128         nvpnManager.updateSubnetNode(subnetId, null, tenantId, networkId, null/*routerID*/, null/*vpnID*/);
129     }
130
131     private void createSubnetToNetworkMapping(Uuid subnetId, Uuid networkId) {
132         try {
133             InstanceIdentifier networkMapIdentifier = NeutronvpnUtils.buildNetworkMapIdentifier(networkId);
134             Optional<NetworkMap> optionalNetworkMap = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION,
135                     networkMapIdentifier);
136             NetworkMapBuilder nwMapBuilder = null;
137             if (optionalNetworkMap.isPresent()) {
138                 nwMapBuilder = new NetworkMapBuilder(optionalNetworkMap.get());
139             } else {
140                 nwMapBuilder = new NetworkMapBuilder().setKey(new NetworkMapKey(networkId)).setNetworkId(networkId);
141                 LOG.debug("Adding a new network node in NetworkMaps DS for network {}", networkId.getValue());
142             }
143             List<Uuid> subnetIdList = nwMapBuilder.getSubnetIdList();
144             if (subnetIdList == null) {
145                 subnetIdList = new ArrayList<>();
146             }
147             subnetIdList.add(subnetId);
148             nwMapBuilder.setSubnetIdList(subnetIdList);
149             MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, networkMapIdentifier, nwMapBuilder.build());
150             LOG.debug("Created subnet-network mapping for subnet {} network {}", subnetId.getValue(),
151                     networkId.getValue());
152         } catch (Exception e) {
153             LOG.error("Create subnet-network mapping failed for subnet {} network {}", subnetId.getValue(),
154                     networkId.getValue());
155         }
156     }
157
158     private void deleteSubnetToNetworkMapping(Uuid subnetId, Uuid networkId) {
159         try {
160             InstanceIdentifier networkMapIdentifier = NeutronvpnUtils.buildNetworkMapIdentifier(networkId);
161             Optional<NetworkMap> optionalNetworkMap = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION,
162                     networkMapIdentifier);
163             if (optionalNetworkMap.isPresent()) {
164                 NetworkMapBuilder nwMapBuilder = new NetworkMapBuilder(optionalNetworkMap.get());
165                 List<Uuid> subnetIdList = nwMapBuilder.getSubnetIdList();
166                 if (subnetIdList.remove(subnetId)) {
167                     if (subnetIdList.size() == 0) {
168                         MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, networkMapIdentifier);
169                         LOG.debug("Deleted network node in NetworkMaps DS for network {}", subnetId.getValue(),
170                                 networkId.getValue());
171                     } else {
172                         nwMapBuilder.setSubnetIdList(subnetIdList);
173                         MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, networkMapIdentifier,
174                                 nwMapBuilder.build());
175                         LOG.debug("Deleted subnet-network mapping for subnet {} network {}", subnetId.getValue(),
176                                 networkId.getValue());
177                     }
178                 } else {
179                     LOG.error("Subnet {} is not mapped to network {}", subnetId.getValue(), networkId.getValue());
180                 }
181             } else {
182                 LOG.error("network {} not present for subnet {} ", networkId, subnetId);
183             }
184         } catch (Exception e) {
185             LOG.error("Delete subnet-network mapping failed for subnet {} network {}", subnetId.getValue(),
186                     networkId.getValue());
187         }
188     }
189 }
190