Merge "Make ActionInfo immutable"
[genius.git] / interfacemanager / interfacemanager-impl / src / main / java / org / opendaylight / genius / interfacemanager / renderer / ovs / statehelpers / OvsInterfaceStateUpdateHelper.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.genius.interfacemanager.renderer.ovs.statehelpers;
9
10 import com.google.common.util.concurrent.ListenableFuture;
11 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
12 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
13 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
14 import org.opendaylight.genius.interfacemanager.IfmConstants;
15 import org.opendaylight.genius.interfacemanager.IfmUtil;
16 import org.opendaylight.genius.interfacemanager.commons.AlivenessMonitorUtils;
17 import org.opendaylight.genius.interfacemanager.commons.InterfaceManagerCommonUtils;
18 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
19 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceBuilder;
20 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey;
21 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
22 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.alivenessmonitor.rev160411.AlivenessMonitorService;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfTunnel;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
28 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
29 import org.slf4j.Logger;
30 import org.slf4j.LoggerFactory;
31
32 import java.util.ArrayList;
33 import java.util.List;
34
35 public class OvsInterfaceStateUpdateHelper {
36     private static final Logger LOG = LoggerFactory.getLogger(OvsInterfaceStateUpdateHelper.class);
37
38     public static List<ListenableFuture<Void>> updateState(InstanceIdentifier<FlowCapableNodeConnector> key,
39                                                            AlivenessMonitorService alivenessMonitorService,
40                                                            DataBroker dataBroker, String interfaceName,
41                                                            FlowCapableNodeConnector flowCapableNodeConnectorNew,
42                                                            FlowCapableNodeConnector flowCapableNodeConnectorOld) {
43         LOG.debug("Update of Interface State for port: {}", interfaceName);
44         List<ListenableFuture<Void>> futures = new ArrayList<>();
45         WriteTransaction transaction = dataBroker.newWriteOnlyTransaction();
46
47         Interface.OperStatus operStatusNew = getOpState(flowCapableNodeConnectorNew);
48         MacAddress macAddressNew = flowCapableNodeConnectorNew.getHardwareAddress();
49
50         Interface.OperStatus operStatusOld = getOpState(flowCapableNodeConnectorOld);
51         MacAddress macAddressOld = flowCapableNodeConnectorOld.getHardwareAddress();
52
53         boolean opstateModified = false;
54         boolean hardwareAddressModified = false;
55         if (!operStatusNew.equals(operStatusOld)) {
56             opstateModified = true;
57         }
58         if (!macAddressNew.equals(macAddressOld)) {
59             hardwareAddressModified = true;
60         }
61
62         if (!opstateModified && !hardwareAddressModified) {
63             LOG.debug("If State entry for port: {} Not Modified.", interfaceName);
64             return futures;
65         }
66
67         InterfaceBuilder ifaceBuilder = new InterfaceBuilder();
68         if (hardwareAddressModified) {
69             LOG.debug("Hw-Address Modified for Port: {}", interfaceName);
70             PhysAddress physAddress = new PhysAddress(macAddressNew.getValue());
71             ifaceBuilder.setPhysAddress(physAddress);
72         }
73         NodeConnectorId nodeConnectorId = InstanceIdentifier.keyOf(key.firstIdentifierOf(NodeConnector.class)).getId();
74         String dpnId = IfmUtil.getDpnFromNodeConnectorId(nodeConnectorId);
75         // modify the attributes in interface operational DS
76         org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface iface =
77                 handleInterfaceStateUpdates(interfaceName, transaction, dataBroker,
78                         ifaceBuilder, opstateModified, flowCapableNodeConnectorNew.getName(), operStatusNew, dpnId);
79
80         // start/stop monitoring based on opState
81         if(modifyTunnel(iface, opstateModified)){
82             handleTunnelMonitoringUpdates(alivenessMonitorService, dataBroker, iface.getAugmentation(IfTunnel.class),
83                     iface.getName(), operStatusNew);
84         }
85
86         futures.add(transaction.submit());
87         return futures;
88     }
89
90     public static void updateInterfaceStateOnNodeRemove(String interfaceName, FlowCapableNodeConnector flowCapableNodeConnector,
91                                                         DataBroker dataBroker, AlivenessMonitorService alivenessMonitorService,
92                                                         WriteTransaction transaction, String dpnId){
93         LOG.debug("Updating interface oper-status to UNKNOWN for : {}", interfaceName);
94
95         InterfaceBuilder ifaceBuilder = new InterfaceBuilder();
96         org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface iface =
97                 handleInterfaceStateUpdates(interfaceName,transaction, dataBroker,
98                         ifaceBuilder, true, flowCapableNodeConnector.getName(),
99                         Interface.OperStatus.Unknown, dpnId);
100         if (InterfaceManagerCommonUtils.isTunnelInterface(iface)){
101             handleTunnelMonitoringUpdates(alivenessMonitorService, dataBroker, iface.getAugmentation(IfTunnel.class),
102                     interfaceName, Interface.OperStatus.Unknown);
103         }
104     }
105
106     public static Interface.OperStatus getOpState(FlowCapableNodeConnector flowCapableNodeConnector){
107         Interface.OperStatus operStatus =
108                 (flowCapableNodeConnector.getState().isLive() &&
109                         !flowCapableNodeConnector.getConfiguration().isPORTDOWN())
110                         ? Interface.OperStatus.Up: Interface.OperStatus.Down;
111         return operStatus;
112     }
113
114     public static org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface
115     handleInterfaceStateUpdates(String interfaceName, WriteTransaction transaction,
116                                 DataBroker dataBroker, InterfaceBuilder ifaceBuilder, boolean opStateModified,
117                                 String portName,
118                                 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus opState,String dpnId){
119         LOG.debug("updating interface state entry for {}", interfaceName);
120         boolean isParentInterface = (interfaceName.equals(portName))?true:false;
121         org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface iface =
122                 InterfaceManagerCommonUtils.getInterfaceFromConfigDS(interfaceName, dataBroker);
123         if (!IfmUtil.isTunnelType(iface, null) && isParentInterface) {
124             interfaceName = new StringBuilder(dpnId).append(IfmConstants.OF_URI_SEPARATOR).append(interfaceName).toString();
125         }
126         InstanceIdentifier<Interface> ifStateId = IfmUtil.buildStateInterfaceId(interfaceName);
127         ifaceBuilder.setKey(new InterfaceKey(interfaceName));
128         // if interface config DS is null, do the update only for the lower-layer-interfaces
129         // which have no corresponding config entries
130         if(iface == null && !isParentInterface){
131             return null;
132         }
133         if (modifyOpState(iface, opStateModified)) {
134             LOG.debug("updating interface oper status as {} for {}", opState.name(), interfaceName);
135             ifaceBuilder.setOperStatus(opState);
136         }
137         transaction.merge(LogicalDatastoreType.OPERATIONAL, ifStateId, ifaceBuilder.build(), false);
138
139         return iface;
140     }
141
142     public static void handleTunnelMonitoringUpdates(AlivenessMonitorService alivenessMonitorService, DataBroker dataBroker,
143                                                      IfTunnel ifTunnel, String interfaceName,
144                                                      Interface.OperStatus operStatus){
145
146         LOG.debug("handling tunnel monitoring updates for {} due to opstate modification", interfaceName);
147         if (operStatus == Interface.OperStatus.Down || operStatus == Interface.OperStatus.Unknown)
148             AlivenessMonitorUtils.stopLLDPMonitoring(alivenessMonitorService, dataBroker, ifTunnel, interfaceName);
149         else
150             AlivenessMonitorUtils.startLLDPMonitoring(alivenessMonitorService, dataBroker, ifTunnel, interfaceName);
151     }
152
153     public static boolean modifyOpState(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface iface,
154                                         boolean opStateModified){
155         return (opStateModified && (iface == null || iface != null && iface.isEnabled()));
156     }
157
158     public static boolean modifyTunnel(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface iface,
159                                        boolean opStateModified){
160         return modifyOpState(iface, opStateModified) && iface != null && iface.getAugmentation(IfTunnel.class) != null;
161     }
162 }