neutron: unbreak of neutron northbound yang model revise
[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
12 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
13 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
14 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
15 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
16 import org.opendaylight.genius.mdsalutil.AbstractDataChangeListener;
17 import org.opendaylight.genius.mdsalutil.MDSALUtil;
18 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
19 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.networks.Network;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.Subnets;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet;
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.yangtools.concepts.ListenerRegistration;
27 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
28 import org.slf4j.Logger;
29 import org.slf4j.LoggerFactory;
30
31 import java.util.ArrayList;
32 import java.util.List;
33
34
35 public class NeutronSubnetChangeListener extends AbstractDataChangeListener<Subnet> implements AutoCloseable {
36     private static final Logger LOG = LoggerFactory.getLogger(NeutronSubnetChangeListener.class);
37
38     private ListenerRegistration<DataChangeListener> listenerRegistration;
39     private final DataBroker broker;
40     private NeutronvpnManager nvpnManager;
41
42
43     public NeutronSubnetChangeListener(final DataBroker db, NeutronvpnManager nVpnMgr) {
44         super(Subnet.class);
45         broker = db;
46         nvpnManager = nVpnMgr;
47         registerListener(db);
48     }
49
50     @Override
51     public void close() throws Exception {
52         if (listenerRegistration != null) {
53             try {
54                 listenerRegistration.close();
55             } catch (final Exception e) {
56                 LOG.error("Error when cleaning up DataChangeListener.", e);
57             }
58             listenerRegistration = null;
59         }
60         LOG.info("N_Subnet listener Closed");
61     }
62
63
64     private void registerListener(final DataBroker db) {
65         try {
66             listenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
67                     InstanceIdentifier.create(Neutron.class).child(Subnets.class).child(Subnet.class),
68                     NeutronSubnetChangeListener.this, DataChangeScope.SUBTREE);
69         } catch (final Exception e) {
70             LOG.error("Neutron Manager Subnet DataChange listener registration fail!", e);
71             throw new IllegalStateException("Neutron Manager Subnet DataChange listener registration failed.", e);
72         }
73     }
74
75     @Override
76     protected void add(InstanceIdentifier<Subnet> identifier, Subnet input) {
77         if (LOG.isTraceEnabled()) {
78             LOG.trace("Adding Subnet : key: " + identifier + ", value=" + input);
79         }
80         Uuid networkId = input.getNetworkId();
81         Network network = NeutronvpnUtils.getNeutronNetwork(broker, networkId);
82         if (network == null || NeutronvpnUtils.isNetworkTypeVlanOrGre(network)) {
83             //FIXME: This should be removed when support for VLAN and GRE network types is added
84             LOG.error("neutron vpn doesn't support vlan/gre network provider type for the port {} which is part of network {}.",
85                     input.getName(), network);
86             return;
87         }
88         handleNeutronSubnetCreated(input.getUuid(), String.valueOf(input.getCidr().getValue()), input.getNetworkId(), input.getTenantId());
89         NeutronvpnUtils.addToSubnetCache(input);
90     }
91
92     @Override
93     protected void remove(InstanceIdentifier<Subnet> identifier, Subnet input) {
94         if (LOG.isTraceEnabled()) {
95             LOG.trace("Removing subnet : key: " + identifier + ", value=" + input);
96         }
97         Uuid networkId = input.getNetworkId();
98         Network network = NeutronvpnUtils.getNeutronNetwork(broker, networkId);
99         if (network == null || NeutronvpnUtils.isNetworkTypeVlanOrGre(network)) {
100             //FIXME: This should be removed when support for VLAN and GRE network types is added
101             LOG.error("neutron vpn doesn't support vlan/gre network provider type for the port {} which is part of network {}.",
102                     input.getName(), network);
103             return;
104         }
105         handleNeutronSubnetDeleted(input.getUuid(), networkId, null);
106         NeutronvpnUtils.removeFromSubnetCache(input);
107     }
108
109     @Override
110     protected void update(InstanceIdentifier<Subnet> identifier, Subnet original, Subnet update) {
111         if (LOG.isTraceEnabled()) {
112             LOG.trace("Updating Subnet : key: " + identifier + ", original value=" + original + ", update value=" +
113                     update);
114         }
115         Uuid networkId = update.getNetworkId();
116         Network network = NeutronvpnUtils.getNeutronNetwork(broker, networkId);
117         if (network == null || NeutronvpnUtils.isNetworkTypeVlanOrGre(network)) {
118             LOG.error("neutron vpn doesn't support vlan/gre network provider type for the port {} which is part of network {}."
119                     + " Skipping the processing of Subnet update DCN", update.getName(), network);
120             return;
121         }
122         handleNeutronSubnetUpdated(update.getUuid(), networkId, update.getTenantId());
123         NeutronvpnUtils.addToSubnetCache(update);
124     }
125
126     private void handleNeutronSubnetCreated(Uuid subnetId, String subnetIp, Uuid networkId, Uuid tenantId) {
127         nvpnManager.updateSubnetNode(subnetId, subnetIp, tenantId, networkId, null, null, null);
128         if (networkId != null) {
129             createSubnetToNetworkMapping(subnetId, networkId);
130         }
131     }
132
133     private void handleNeutronSubnetDeleted(Uuid subnetId, Uuid networkId, Uuid tenantId) {
134         Uuid vpnId = NeutronvpnUtils.getVpnForNetwork(broker, networkId);
135         if (vpnId != null) {
136             nvpnManager.removeSubnetFromVpn(vpnId, subnetId);
137         }
138         if (networkId != null)  {
139             deleteSubnetToNetworkMapping(subnetId, networkId);
140         }
141         nvpnManager.deleteSubnetMapNode(subnetId);
142     }
143
144     private void handleNeutronSubnetUpdated(Uuid subnetId, Uuid networkId, Uuid tenantId) {
145         Uuid oldNetworkId = NeutronvpnUtils.getSubnetmap(broker, subnetId).getNetworkId();
146         if (oldNetworkId != null && !oldNetworkId.equals(networkId)) {
147             deleteSubnetToNetworkMapping(subnetId, oldNetworkId);
148         }
149         if (networkId != null && !networkId.equals(oldNetworkId)) {
150             createSubnetToNetworkMapping(subnetId, networkId);
151         }
152         nvpnManager.updateSubnetNode(subnetId, null, tenantId, networkId, null, null, null);
153     }
154
155     private void createSubnetToNetworkMapping(Uuid subnetId, Uuid networkId) {
156         try {
157             InstanceIdentifier networkMapIdentifier = NeutronvpnUtils.buildNetworkMapIdentifier(networkId);
158             Optional<NetworkMap> optionalNetworkMap = NeutronvpnUtils.read(broker, LogicalDatastoreType.CONFIGURATION,
159                     networkMapIdentifier);
160             NetworkMapBuilder nwMapBuilder = null;
161             if (optionalNetworkMap.isPresent()) {
162                 nwMapBuilder = new NetworkMapBuilder(optionalNetworkMap.get());
163             } else {
164                 nwMapBuilder = new NetworkMapBuilder().setKey(new NetworkMapKey(networkId)).setNetworkId(networkId);
165                 LOG.debug("Adding a new network node in NetworkMaps DS for network {}", networkId.getValue());
166             }
167             List<Uuid> subnetIdList = nwMapBuilder.getSubnetIdList();
168             if (subnetIdList == null) {
169                 subnetIdList = new ArrayList<>();
170             }
171             subnetIdList.add(subnetId);
172             nwMapBuilder.setSubnetIdList(subnetIdList);
173             MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, networkMapIdentifier, nwMapBuilder.build());
174             LOG.debug("Created subnet-network mapping for subnet {} network {}", subnetId.getValue(),
175                     networkId.getValue());
176         } catch (Exception e) {
177             LOG.error("Create subnet-network mapping failed for subnet {} network {}", subnetId.getValue(),
178                     networkId.getValue());
179         }
180     }
181
182     private void deleteSubnetToNetworkMapping(Uuid subnetId, Uuid networkId) {
183         try {
184             InstanceIdentifier networkMapIdentifier = NeutronvpnUtils.buildNetworkMapIdentifier(networkId);
185             Optional<NetworkMap> optionalNetworkMap = NeutronvpnUtils.read(broker, LogicalDatastoreType.CONFIGURATION,
186                     networkMapIdentifier);
187             if (optionalNetworkMap.isPresent()) {
188                 NetworkMapBuilder nwMapBuilder = new NetworkMapBuilder(optionalNetworkMap.get());
189                 List<Uuid> subnetIdList = nwMapBuilder.getSubnetIdList();
190                 if (subnetIdList.remove(subnetId)) {
191                     if (subnetIdList.size() == 0) {
192                         MDSALUtil.syncDelete(broker, LogicalDatastoreType.CONFIGURATION, networkMapIdentifier);
193                         LOG.debug("Deleted network node in NetworkMaps DS for network {}", subnetId.getValue(),
194                                 networkId.getValue());
195                     } else {
196                         nwMapBuilder.setSubnetIdList(subnetIdList);
197                         MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, networkMapIdentifier,
198                                 nwMapBuilder.build());
199                         LOG.debug("Deleted subnet-network mapping for subnet {} network {}", subnetId.getValue(),
200                                 networkId.getValue());
201                     }
202                 } else {
203                     LOG.error("Subnet {} is not mapped to network {}", subnetId.getValue(), networkId.getValue());
204                 }
205             } else {
206                 LOG.error("network {} not present for subnet {} ", networkId, subnetId);
207             }
208         } catch (Exception e) {
209             LOG.error("Delete subnet-network mapping failed for subnet {} network {}", subnetId.getValue(),
210                     networkId.getValue());
211         }
212     }
213 }