[ONOS-2885] Resolve flow installation failure bug

There is a time gap between
controller is elected as the master of a switch
and
controller actually becomes the master of a switch (receives ROLE_REPLY).
During this time gap, OF messages destined for the switch will be sent to this controller.
However, the OF message can only be sent to the switch after controller receives the ROLE_REPLY.

Change-Id: I32d68384226e272658a0c9de2d32ae9e1cc39b6a
diff --git a/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/AbstractOpenFlowSwitch.java b/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/AbstractOpenFlowSwitch.java
index 2f6357b..2c19837 100644
--- a/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/AbstractOpenFlowSwitch.java
+++ b/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/AbstractOpenFlowSwitch.java
@@ -79,6 +79,8 @@
     protected OFFeaturesReply features;
     protected OFDescStatsReply desc;
 
+    List<OFMessage> messagesPendingMastership;
+
     @Override
     public void init(Dpid dpid, OFDescStatsReply desc, OFVersion ofv) {
         this.dpid = dpid;
@@ -96,16 +98,21 @@
     }
 
     @Override
-    public void sendMsg(OFMessage m) {
-        if (role == RoleState.MASTER && channel.isConnected()) {
-            channel.write(Collections.singletonList(m));
-        }
+    public void sendMsg(OFMessage msg) {
+        this.sendMsg(Collections.singletonList(msg));
     }
 
     @Override
     public final void sendMsg(List<OFMessage> msgs) {
         if (role == RoleState.MASTER && channel.isConnected()) {
             channel.write(msgs);
+        } else if (messagesPendingMastership != null) {
+            messagesPendingMastership.addAll(msgs);
+            log.debug("Enqueue message for switch {}. queue size after is {}",
+                      dpid, messagesPendingMastership.size());
+        } else {
+            log.warn("Dropping message for switch {} (role: {}, connected: {}): {}",
+                     dpid, role, channel.isConnected(), msgs);
         }
     }
 
@@ -232,6 +239,12 @@
     @Override
     public final void transitionToMasterSwitch() {
         this.agent.transitionToMasterSwitch(dpid);
+        if (messagesPendingMastership != null) {
+            this.sendMsg(messagesPendingMastership);
+            log.debug("Sending {} pending messages to switch {}",
+                     messagesPendingMastership.size(), dpid);
+            messagesPendingMastership = null;
+        }
     }
 
     @Override
@@ -278,6 +291,11 @@
                 log.debug("Sending role {} to switch {}", role, getStringId());
                 if (role == RoleState.SLAVE || role == RoleState.EQUAL) {
                     this.role = role;
+                } else {
+                    if (messagesPendingMastership == null) {
+                        log.debug("Initializing new queue for switch {}", dpid);
+                        messagesPendingMastership = new ArrayList<>();
+                    }
                 }
             } else {
                 this.role = role;