ac0d853df726e64b6139953ee55c5050c54fe621
[netvirt.git] / vpnservice / neutronvpn / neutronvpn-impl / src / main / java / org / opendaylight / netvirt / neutronvpn / NeutronNetworkChangeListener.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
9 package org.opendaylight.netvirt.neutronvpn;
10
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.netvirt.neutronvpn.api.utils.NeutronUtils;
19 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanInstances;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.SegmentTypeBase;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstance;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstanceBuilder;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstanceKey;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.ext.rev150712.NetworkL3Extension;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.Networks;
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.yangtools.concepts.ListenerRegistration;
29 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
30 import org.slf4j.Logger;
31 import org.slf4j.LoggerFactory;
32
33
34 public class NeutronNetworkChangeListener extends AbstractDataChangeListener<Network> implements AutoCloseable {
35     private static final Logger LOG = LoggerFactory.getLogger(NeutronNetworkChangeListener.class);
36
37     private ListenerRegistration<DataChangeListener> listenerRegistration;
38     private final DataBroker broker;
39     private NeutronvpnManager nvpnManager;
40     private NeutronvpnNatManager nvpnNatManager;
41
42
43     public NeutronNetworkChangeListener(final DataBroker db, NeutronvpnManager nVpnMgr,
44                                         NeutronvpnNatManager nVpnNatMgr) {
45         super(Network.class);
46         broker = db;
47         nvpnManager = nVpnMgr;
48         nvpnNatManager = nVpnNatMgr;
49         registerListener(db);
50     }
51
52     @Override
53     public void close() throws Exception {
54         if (listenerRegistration != null) {
55             try {
56                 listenerRegistration.close();
57             } catch (final Exception e) {
58                 LOG.error("Error when cleaning up DataChangeListener.", e);
59             }
60             listenerRegistration = null;
61         }
62         LOG.info("N_Network listener Closed");
63     }
64
65
66     private void registerListener(final DataBroker db) {
67         try {
68             listenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
69                     InstanceIdentifier.create(Neutron.class).
70                             child(Networks.class).child(Network.class),
71                     NeutronNetworkChangeListener.this, DataChangeScope.SUBTREE);
72             LOG.info("Neutron Manager Network DataChange listener registration Success!");
73         } catch (final Exception e) {
74             LOG.error("Neutron Manager Network DataChange listener registration fail!", e);
75             throw new IllegalStateException("Neutron Manager Network DataChange listener registration failed.", e);
76         }
77     }
78
79     @Override
80     protected void add(InstanceIdentifier<Network> identifier, Network input) {
81         if (LOG.isTraceEnabled()) {
82             LOG.trace("Adding Network : key: " + identifier + ", value=" + input);
83         }
84         if (!NeutronvpnUtils.isNetworkTypeSupported(input)) {
85             //FIXME: This should be removed when support for GRE network types is added
86             LOG.error("Neutronvpn doesn't support gre network provider type for this network {}.", input);
87             return;
88         }
89         // Create ELAN instance for this network
90         ElanInstance elanInstance = createElanInstance(input);
91         // Create ELAN interface and IETF interfaces for the physical network
92         NeutronvpnServiceAccessor.getElanProvider().createExternalElanNetwork(elanInstance);
93         if (input.getAugmentation(NetworkL3Extension.class).isExternal()) {
94             nvpnNatManager.addExternalNetwork(input);
95             NeutronvpnUtils.addToNetworkCache(input);
96         }
97     }
98
99     @Override
100     protected void remove(InstanceIdentifier<Network> identifier, Network input) {
101         if (LOG.isTraceEnabled()) {
102             LOG.trace("Removing Network : key: " + identifier + ", value=" + input);
103         }
104         if (!NeutronvpnUtils.isNetworkTypeSupported(input)) {
105             //FIXME: This should be removed when support for GRE network types is added
106             LOG.error("Neutronvpn doesn't support gre network provider type for this network {}.", input);
107             return;
108         }
109         //Delete ELAN instance for this network
110         String elanInstanceName = input.getUuid().getValue();
111         deleteElanInstance(elanInstanceName);
112         if (input.getAugmentation(NetworkL3Extension.class).isExternal()) {
113             nvpnNatManager.removeExternalNetwork(input);
114             NeutronvpnUtils.removeFromNetworkCache(input);
115         }
116
117         // TODO: delete elan-interfaces for physnet port
118     }
119
120     @Override
121     protected void update(InstanceIdentifier<Network> identifier, Network original, Network update) {
122         if (LOG.isTraceEnabled()) {
123             LOG.trace("Updating Network : key: " + identifier + ", original value=" + original + ", update value=" +
124                     update);
125         }
126     }
127
128     private ElanInstance createElanInstance(Network input) {
129         String elanInstanceName = input.getUuid().getValue();
130         Class<? extends SegmentTypeBase> segmentType = NeutronvpnUtils.getSegmentTypeFromNeutronNetwork(input);
131         String segmentationId = NeutronUtils.getSegmentationIdFromNeutronNetwork(input);
132         String physicalNetworkName = NeutronvpnUtils.getPhysicalNetworkName(input);
133         ElanInstanceBuilder elanInstanceBuilder = new ElanInstanceBuilder().setElanInstanceName(elanInstanceName);
134         if (segmentType != null) {
135             elanInstanceBuilder.setSegmentType(segmentType);
136             if (segmentationId != null) {
137                 elanInstanceBuilder.setSegmentationId(Long.valueOf(segmentationId));
138             }
139             if (physicalNetworkName != null) {
140                 elanInstanceBuilder.setPhysicalNetworkName(physicalNetworkName);
141             }
142         }
143         elanInstanceBuilder.setKey(new ElanInstanceKey(elanInstanceName));
144         ElanInstance elanInstance = elanInstanceBuilder.build();
145         InstanceIdentifier<ElanInstance> id = InstanceIdentifier.builder(ElanInstances.class)
146                 .child(ElanInstance.class, new ElanInstanceKey(elanInstanceName)).build();
147         MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, id, elanInstance);
148         return elanInstance;
149     }
150
151     private void deleteElanInstance(String elanInstanceName) {
152         InstanceIdentifier<ElanInstance> id = InstanceIdentifier.builder(ElanInstances.class)
153                 .child(ElanInstance.class, new ElanInstanceKey(elanInstanceName)).build();
154         MDSALUtil.syncDelete(broker, LogicalDatastoreType.CONFIGURATION, id);
155     }
156
157 }