Merge "Fix for openflow devices not connecting to controller"
[openflowplugin.git] / applications / forwardingrules-manager / src / main / java / org / opendaylight / openflowplugin / applications / frm / util / FrmUtil.java
1 /*
2  * Copyright (c) 2018 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.openflowplugin.applications.frm.util;
10
11 import java.lang.management.ManagementFactory;
12 import java.util.ArrayList;
13 import java.util.Collection;
14 import java.util.Collections;
15 import java.util.concurrent.ExecutionException;
16 import java.util.concurrent.TimeUnit;
17 import java.util.concurrent.TimeoutException;
18 import javax.management.AttributeNotFoundException;
19 import javax.management.InstanceNotFoundException;
20 import javax.management.MBeanException;
21 import javax.management.MBeanServer;
22 import javax.management.MalformedObjectNameException;
23 import javax.management.ObjectName;
24 import javax.management.ReflectionException;
25 import org.opendaylight.openflowplugin.applications.frm.ActionType;
26 import org.opendaylight.openflowplugin.applications.frm.ForwardingRulesManager;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.GroupActionCase;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowTableRef;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowRef;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCase;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.WriteActionsCase;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupId;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.GroupKey;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.rev170124.BundleId;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflowplugin.app.arbitrator.reconcile.service.rev180227.GetActiveBundleInputBuilder;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflowplugin.app.arbitrator.reconcile.service.rev180227.GetActiveBundleOutput;
48 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
49 import org.opendaylight.yangtools.yang.common.RpcResult;
50 import org.opendaylight.yangtools.yang.common.Uint32;
51 import org.opendaylight.yangtools.yang.common.Uint64;
52 import org.opendaylight.yangtools.yang.common.Uint8;
53 import org.slf4j.Logger;
54 import org.slf4j.LoggerFactory;
55
56 @SuppressWarnings("IllegalCatch")
57 public final class FrmUtil {
58     private static final Logger LOG = LoggerFactory.getLogger(FrmUtil.class);
59     private static final String SEPARATOR = ":";
60     private static final long RPC_RESULT_TIMEOUT = 2500;
61     public static final String OPENFLOW_PREFIX = "openflow:";
62
63     private static final String JMX_OBJ_NAME_LIST_OF_SHRDS = "org.opendaylight.controller:type="
64             + "DistributedConfigDatastore,Category=ShardManager,name=shard-manager-config";
65     private static String JMX_OBJECT_SHARD_STATUS = "";
66
67     private FrmUtil() {
68         throw new IllegalStateException("This class should not be instantiated.");
69     }
70
71     public static NodeId getNodeIdFromNodeIdentifier(final InstanceIdentifier<FlowCapableNode> nodeIdent) {
72         return nodeIdent.firstKeyOf(Node.class).getId();
73     }
74
75     public static String getNodeIdValueFromNodeIdentifier(final InstanceIdentifier<FlowCapableNode> nodeIdent) {
76         return getNodeIdFromNodeIdentifier(nodeIdent).getValue();
77     }
78
79     public static String getFlowId(final FlowRef flowRef) {
80         return flowRef.getValue().firstKeyOf(Flow.class).getId().getValue();
81     }
82
83     public static String getFlowId(final InstanceIdentifier<Flow> identifier) {
84         return getFlowId(new FlowRef(identifier));
85     }
86
87     public static Uint8 getTableId(final FlowTableRef flowTableRef) {
88         return flowTableRef.getValue().firstKeyOf(Table.class).getId();
89     }
90
91     public static Uint8 getTableId(final InstanceIdentifier<Flow> identifier) {
92         return getTableId(new FlowTableRef(identifier));
93     }
94
95     public static Uint64 getDpnIdFromNodeName(final InstanceIdentifier<FlowCapableNode> nodeIdent) {
96         String nodeId = nodeIdent.firstKeyOf(Node.class).getId().getValue();
97         return Uint64.valueOf(nodeId.substring(nodeId.lastIndexOf(SEPARATOR) + 1));
98     }
99
100     public static Uint32 isFlowDependentOnGroup(final Flow flow) {
101         LOG.debug("Check if flow {} is dependent on group", flow);
102         if (flow.getInstructions() != null) {
103             Collection<Instruction> instructions = flow.getInstructions().nonnullInstruction().values();
104             for (Instruction instruction : instructions) {
105                 Collection<Action> actions = Collections.emptyList();
106                 if (instruction.getInstruction().implementedInterface()
107                         .equals(ActionType.APPLY_ACTION.getActionType())) {
108                     actions = ((ApplyActionsCase) instruction.getInstruction())
109                             .getApplyActions().nonnullAction().values();
110                 } else if (instruction.getInstruction().implementedInterface()
111                         .equals(ActionType.WRITE_ACTION.getActionType())) {
112                     actions = ((WriteActionsCase)instruction.getInstruction())
113                             .getWriteActions().nonnullAction().values();
114                 }
115                 if (actions != null) {
116                     for (Action action : actions) {
117                         if (action.getAction().implementedInterface().equals(ActionType.GROUP_ACTION.getActionType())) {
118                             return ((GroupActionCase) action.getAction()).getGroupAction().getGroupId();
119                         }
120                     }
121                 }
122             }
123         }
124         return null;
125     }
126
127     public static InstanceIdentifier<Group> buildGroupInstanceIdentifier(
128             final InstanceIdentifier<FlowCapableNode> nodeIdent, final Uint32 groupId) {
129         NodeId nodeId = getNodeIdFromNodeIdentifier(nodeIdent);
130         InstanceIdentifier<Group> groupInstanceId = InstanceIdentifier.builder(Nodes.class)
131                 .child(Node.class, new NodeKey(nodeId))
132                 .augmentation(FlowCapableNode.class)
133                 .child(Group.class, new GroupKey(new GroupId(groupId)))
134                 .build();
135         return groupInstanceId;
136     }
137
138     public static BundleId getActiveBundle(final InstanceIdentifier<FlowCapableNode> nodeIdent,
139                                            final ForwardingRulesManager provider) {
140         final Uint64 dpId = getDpnIdFromNodeName(nodeIdent);
141         final NodeRef nodeRef = new NodeRef(nodeIdent.firstIdentifierOf(Node.class));
142         GetActiveBundleInputBuilder input = new GetActiveBundleInputBuilder().setNodeId(dpId).setNode(nodeRef);
143         try {
144             RpcResult<GetActiveBundleOutput> result = provider.getArbitratorReconciliationManager()
145                     .getActiveBundle(input.build()).get(RPC_RESULT_TIMEOUT, TimeUnit.MILLISECONDS);
146             if (!result.isSuccessful()) {
147                 LOG.trace("Error while retrieving active bundle present for node {}", dpId);
148             } else {
149                 return result.getResult().getResult();
150             }
151         } catch (InterruptedException | ExecutionException | TimeoutException e) {
152             LOG.error("Error while retrieving active bundle present for node {} is {}", dpId , e.getMessage());
153         }
154         return null;
155     }
156
157     public static boolean isGroupExistsOnDevice(final InstanceIdentifier<FlowCapableNode> nodeIdent,
158                                                 final Uint32 groupId,
159                                                 final ForwardingRulesManager provider) {
160         String nodeId = getNodeIdValueFromNodeIdentifier(nodeIdent);
161         return provider.getDevicesGroupRegistry().isGroupPresent(nodeId, groupId);
162     }
163
164     public static String getInventoryConfigDataStoreStatus() {
165         boolean statusResult = true;
166         try {
167             ArrayList listOfShards = getAttributeJMXCommand(JMX_OBJ_NAME_LIST_OF_SHRDS, "LocalShards");
168             if (listOfShards != null) {
169                 for (Object listOfShard : listOfShards) {
170                     LOG.info("Listofshard is  {} ",listOfShard);
171                     if (listOfShard.toString().contains("inventory")) {
172                         JMX_OBJECT_SHARD_STATUS =
173                                 "org.opendaylight.controller:Category=Shards,name=" + listOfShard
174                                         + ",type=DistributedConfigDatastore";
175                         LOG.info("JMX object shard status is {} ",JMX_OBJECT_SHARD_STATUS);
176                         String leader = getLeaderJMX(JMX_OBJECT_SHARD_STATUS, "Leader");
177                         if (leader != null && leader.length() > 1) {
178                             LOG.info("{} ::Inventory Shard has the Leader as:: {}", listOfShard, leader);
179                         } else {
180                             statusResult = false;
181                         }
182                     }
183                 }
184             }
185         } catch (Exception e) {
186             LOG.error("ERROR ::", e);
187         }
188         if (statusResult) {
189             return "OPERATIONAL";
190         } else {
191             return "ERROR";
192         }
193     }
194
195     private static ArrayList getAttributeJMXCommand(String objectName, String attributeName) {
196         MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
197         ArrayList listOfShards = new ArrayList();
198         if (mbs != null) {
199             try {
200                 listOfShards = (ArrayList) mbs.getAttribute(new ObjectName(objectName), attributeName);
201             } catch (MBeanException | AttributeNotFoundException | InstanceNotFoundException
202                     | MalformedObjectNameException | ReflectionException e) {
203                 LOG.error("Exception while reading list of shards ", e);
204             }
205         }
206         return listOfShards;
207     }
208
209     private static String getLeaderJMX(String objectName, String atrName) {
210         MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
211         String leader = "";
212         if (mbs != null) {
213             try {
214                 leader  = (String) mbs.getAttribute(new ObjectName(objectName), atrName);
215             } catch (MalformedObjectNameException monEx) {
216                 LOG.error("CRITICAL EXCEPTION : Malformed Object Name Exception");
217             } catch (MBeanException mbEx) {
218                 LOG.error("CRITICAL EXCEPTION : MBean Exception");
219             } catch (InstanceNotFoundException infEx) {
220                 LOG.error("CRITICAL EXCEPTION : Instance Not Found Exception");
221             } catch (ReflectionException rEx) {
222                 LOG.error("CRITICAL EXCEPTION : Reflection Exception");
223             } catch (Exception e) {
224                 LOG.error("Attribute not found");
225             }
226         }
227         return leader;
228     }
229 }