66a10fa313b41ce89c4eec7493dd4da2351d9dd9
[netvirt.git] / qosservice / impl / src / main / java / org / opendaylight / netvirt / qosservice / QosInterfaceStateChangeListener.java
1 /*
2  * Copyright (c) 2017 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.qosservice;
10
11 import com.google.common.base.Optional;
12 import java.util.Collections;
13 import javax.annotation.PostConstruct;
14 import javax.inject.Inject;
15 import javax.inject.Singleton;
16 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
17 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
18 import org.opendaylight.genius.datastoreutils.AsyncClusteredDataTreeChangeListenerBase;
19 import org.opendaylight.genius.mdsalutil.NwConstants;
20 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
21 import org.opendaylight.netvirt.neutronvpn.interfaces.INeutronVpnManager;
22 import org.opendaylight.netvirt.qosservice.recovery.QosServiceRecoveryHandler;
23 import org.opendaylight.serviceutils.srm.RecoverableListener;
24 import org.opendaylight.serviceutils.srm.ServiceRecoveryRegistry;
25 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev170119.L2vlan;
26 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
27 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
28 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.networks.Network;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.qos.ext.rev160613.QosNetworkExtension;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.qos.ext.rev160613.QosPortExtension;
33 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
34 import org.slf4j.Logger;
35 import org.slf4j.LoggerFactory;
36
37 @Singleton
38 public class QosInterfaceStateChangeListener extends AsyncClusteredDataTreeChangeListenerBase<Interface,
39         QosInterfaceStateChangeListener> implements RecoverableListener {
40
41     private static final Logger LOG = LoggerFactory.getLogger(QosInterfaceStateChangeListener.class);
42
43     private final DataBroker dataBroker;
44     private final UuidUtil uuidUtil;
45     private final QosAlertManager qosAlertManager;
46     private final QosNeutronUtils qosNeutronUtils;
47     private final INeutronVpnManager neutronVpnManager;
48     private final JobCoordinator jobCoordinator;
49
50     @Inject
51     public QosInterfaceStateChangeListener(final DataBroker dataBroker, final QosAlertManager qosAlertManager,
52                                            final QosNeutronUtils qosNeutronUtils,
53                                            final INeutronVpnManager neutronVpnManager,
54                                            final ServiceRecoveryRegistry serviceRecoveryRegistry,
55                                            final QosServiceRecoveryHandler qosServiceRecoveryHandler,
56                                            final JobCoordinator jobCoordinator) {
57         super(Interface.class, QosInterfaceStateChangeListener.class);
58         this.dataBroker = dataBroker;
59         this.uuidUtil = new UuidUtil();
60         this.qosAlertManager = qosAlertManager;
61         this.qosNeutronUtils = qosNeutronUtils;
62         this.neutronVpnManager = neutronVpnManager;
63         this.jobCoordinator = jobCoordinator;
64         serviceRecoveryRegistry.addRecoverableListener(qosServiceRecoveryHandler.buildServiceRegistryKey(),
65                 this);
66         LOG.trace("{} created",  getClass().getSimpleName());
67     }
68
69     @PostConstruct
70     public void init() {
71         registerListener();
72         LOG.trace("{} init and registerListener done", getClass().getSimpleName());
73     }
74
75     @Override
76     public void registerListener() {
77         registerListener(LogicalDatastoreType.OPERATIONAL, dataBroker);
78     }
79
80     @Override
81     protected InstanceIdentifier<Interface> getWildCardPath() {
82         return InstanceIdentifier.create(InterfacesState.class).child(Interface.class);
83     }
84
85     @Override
86     protected QosInterfaceStateChangeListener getDataTreeChangeListener() {
87         return QosInterfaceStateChangeListener.this;
88     }
89
90     @Override
91     @SuppressWarnings("checkstyle:IllegalCatch")
92     protected void add(InstanceIdentifier<Interface> identifier, Interface intrf) {
93         if (L2vlan.class.equals(intrf.getType())) {
94             final String interfaceName = intrf.getName();
95             getNeutronPort(interfaceName).ifPresent(port -> {
96                 Network network = qosNeutronUtils.getNeutronNetwork(port.getNetworkId());
97                 LOG.debug("Qos Service : Received interface {} PORT UP event ", interfaceName);
98                 if (port.augmentation(QosPortExtension.class) != null) {
99                     Uuid portQosUuid = port.augmentation(QosPortExtension.class).getQosPolicyId();
100                     if (portQosUuid != null) {
101                         qosNeutronUtils.addToQosPortsCache(portQosUuid, port);
102                         qosNeutronUtils.handleQosInterfaceAdd(port, portQosUuid);
103                     }
104                 } else {
105                     if (network.augmentation(QosNetworkExtension.class) != null) {
106                         Uuid networkQosUuid = network.augmentation(QosNetworkExtension.class).getQosPolicyId();
107                         if (networkQosUuid != null) {
108                             qosNeutronUtils.handleQosInterfaceAdd(port, networkQosUuid);
109                         }
110                     }
111                 }
112                 qosAlertManager.processInterfaceUpEvent(interfaceName);
113             });
114         }
115     }
116
117     private java.util.Optional<Port> getNeutronPort(String portName) {
118         return uuidUtil.newUuidIfValidPattern(portName)
119                 .toJavaUtil()
120                 .map(qosNeutronUtils::getNeutronPort);
121     }
122
123     private Optional<Port> getNeutronPortForRemove(Interface intrf) {
124         final String portName = intrf.getName();
125         Optional<Uuid> uuid = uuidUtil.newUuidIfValidPattern(portName);
126         if (uuid.isPresent()) {
127             Port port = qosNeutronUtils.getNeutronPort(portName);
128             if (port != null) {
129                 return Optional.fromJavaUtil(uuid.toJavaUtil().map(qosNeutronUtils::getNeutronPort));
130             }
131             if (qosNeutronUtils.isBindServiceDone(uuid)) {
132                 LOG.trace("Qos Service : interface {} clearing stale flow entries if any", portName);
133                 jobCoordinator.enqueueJob("QosPort-" + portName, () -> {
134                     qosNeutronUtils.removeStaleFlowEntry(intrf, NwConstants.ETHTYPE_IPV4);
135                     qosNeutronUtils.removeStaleFlowEntry(intrf, NwConstants.ETHTYPE_IPV6);
136                     qosNeutronUtils.unbindservice(portName);
137                     qosNeutronUtils.removeInterfaceInQosConfiguredPorts(uuid);
138                     return Collections.emptyList();
139                 });
140             }
141         }
142         return Optional.absent();
143     }
144
145     @Override
146     protected void remove(InstanceIdentifier<Interface> identifier, Interface intrf) {
147         if (L2vlan.class.equals(intrf.getType())) {
148             final String interfaceName = intrf.getName();
149             // Guava Optional asSet().forEach() emulates Java 8 Optional ifPresent()
150             getNeutronPortForRemove(intrf).asSet().forEach(port -> {
151                 LOG.trace("Qos Service : Received interface {} PORT DOWN event ", interfaceName);
152
153                 String lowerLayerIf = intrf.getLowerLayerIf().get(0);
154                 LOG.trace("lowerLayerIf {}", lowerLayerIf);
155                 qosAlertManager.removeLowerLayerIfFromQosAlertCache(lowerLayerIf);
156                 QosPortExtension removeQos = port.augmentation(QosPortExtension.class);
157                 if (removeQos != null) {
158                     qosNeutronUtils.handleNeutronPortRemove(port, removeQos.getQosPolicyId(), intrf);
159                     qosNeutronUtils.removeFromQosPortsCache(removeQos.getQosPolicyId(), port);
160                 } else {
161                     Network network = qosNeutronUtils.getNeutronNetwork(port.getNetworkId());
162                     if (network != null && network.augmentation(QosNetworkExtension.class) != null) {
163                         Uuid networkQosUuid = network.augmentation(QosNetworkExtension.class).getQosPolicyId();
164                         if (networkQosUuid != null) {
165                             qosNeutronUtils.handleNeutronPortRemove(port, networkQosUuid, intrf);
166                         }
167                     }
168                 }
169             });
170         }
171     }
172
173     @Override
174     protected void update(InstanceIdentifier<Interface> identifier, Interface original, Interface update) {
175         if (original.getType() == null && L2vlan.class.equals(update.getType())) {
176             // IfType was missing at creation, add it now
177             add(identifier, update);
178         }
179     }
180 }
181
182