checking olt state connection rather than assuming we can connect

Change-Id: I732dd9dd94de8df106e0d7551bccab2e7cb53515
diff --git a/voltha/adapters/microsemi/PAS5211_comm.py b/voltha/adapters/microsemi/PAS5211_comm.py
index 0529fbe..d604077 100644
--- a/voltha/adapters/microsemi/PAS5211_comm.py
+++ b/voltha/adapters/microsemi/PAS5211_comm.py
@@ -14,6 +14,7 @@
 # limitations under the License.
 #
 import netifaces
+import select
 from scapy.layers.l2 import Dot3
 from scapy.sendrecv import srp1
 import structlog
@@ -69,6 +70,13 @@
             frame = constructPAS5211Frames(msg, self.seqgen.next(), self.src_mac,
                                            self.dst_mac, channel_id=self.channel_id,
                                            **kwargs)
-            return srp1(frame, timeout=timeout, iface=self.iface)
+            try:
+                return srp1(frame, timeout=timeout, iface=self.iface)
+            except IOError as exc:
+                log.info('Can not communicate to ruby on mac {} because {}'
+                         .format(self.dst_mac, exc.message))
+            except select.error as exc:
+                log.info('Can not communicate to ruby on mac {} because {}'
+                         .format(self.dst_mac, exc))
         else:
             log.info('Unknown src mac for {}'.format(self.iface))
diff --git a/voltha/adapters/microsemi/RubyAdapter.py b/voltha/adapters/microsemi/RubyAdapter.py
index bc1d0be..1083265 100644
--- a/voltha/adapters/microsemi/RubyAdapter.py
+++ b/voltha/adapters/microsemi/RubyAdapter.py
@@ -17,11 +17,12 @@
 """
 Microsemi/Celestica Ruby vOLTHA adapter.
 """
+import time
 import structlog
 from twisted.internet import reactor
 from voltha.adapters.interface import IAdapterInterface
 from voltha.adapters.microsemi.PAS5211_comm import PAS5211Communication
-from voltha.adapters.microsemi.StateMachine import Disconnected
+from voltha.adapters.microsemi.StateMachine import Disconnected, States
 
 from voltha.protos import third_party
 from voltha.protos.adapter_pb2 import Adapter, AdapterConfig, DeviceTypes
@@ -86,8 +87,16 @@
         raise NotImplementedError()
 
     def init_olt(self):
-        self.olt.run()
-        self.olt = self.olt.transition()
-        self.olt.run()
-        self.olt = self.olt.transition()
-        self.olt.run()
\ No newline at end of file
+        olt = self.olt
+        while not olt.abandon():
+            if olt.state() == States.DISCONNECTED or olt.state() == States.FETCH_VERSION:
+                olt.run()
+                olt = olt.transition()
+            elif olt.state() == States.CONNECTED:
+                olt.run()
+                break
+        if olt.abandon():
+            #TODO Add more info here
+            log.info('Disconnecting this OLT')
+            self.stop()
+        self.olt = olt
diff --git a/voltha/adapters/microsemi/StateMachine.py b/voltha/adapters/microsemi/StateMachine.py
index 67ffb2f..d2f4a50 100644
--- a/voltha/adapters/microsemi/StateMachine.py
+++ b/voltha/adapters/microsemi/StateMachine.py
@@ -17,15 +17,21 @@
 """
 Base OLT State machine class
 """
-import threading
 import time
+
 from structlog import get_logger
 from twisted.internet import reactor, task
 from voltha.adapters.microsemi.PAS5211 import PAS5211MsgGetProtocolVersion, PAS5211MsgGetOltVersion
 
 log = get_logger()
 
+class States(object):
+    DISCONNECTED = 0
+    FETCH_VERSION = 1
+    CONNECTED = 2
+
 class State(object):
+
     def __init__(self):
         pass
 
@@ -36,13 +42,19 @@
         raise NotImplementedError()
 
     """
-    Distates which state to transtion to.
+    Dictates which state to transtion to.
     Predicated on the run operation to be successful.
     """
     def transition(self):
         raise NotImplementedError()
 
     """
+    Returns the current state name
+    """
+    def state(self):
+        raise NotImplementedError()
+
+    """
     Returns any useful information for the given State
     """
     def value(self):
@@ -60,26 +72,43 @@
     def disconnect(self):
         raise NotImplementedError()
 
+    """
+    Indicates whether to abandon trying to connect.
+    """
+    def abandon(self):
+        raise  NotImplementedError()
+
 """
 Represents an OLT in disconnected or pre init state.
 """
 class Disconnected(State):
 
-    def __init__(self, pas_comm):
+    def __init__(self, pas_comm, retry=3):
         self.comm = pas_comm
         self.completed = False
         self.packet = None
+        self.retry = retry
+        self.attempt = 1
 
     def run(self):
         self.packet = self.comm.communicate(PAS5211MsgGetProtocolVersion())
-        self.packet.show()
         if self.packet is not None:
+            self.packet.show()
             self.completed = True
+        else:
+            if self.attempt <= self.retry:
+                time.sleep(self.attempt)
+                self.attempt += 1
         return self.completed
 
     def transition(self):
         if self.completed:
             return Fetch_Version(self.comm)
+        else:
+            return self
+
+    def state(self):
+        return States.DISCONNECTED
 
     def value(self):
         # TODO return a nicer value than the packet.
@@ -89,7 +118,10 @@
         raise NotImplementedError()
 
     def disconnect(self):
-        raise NotImplementedError()
+        pass
+
+    def abandon(self):
+        return self.attempt > self.retry
 
 """
 Fetches the OLT version
@@ -102,14 +134,19 @@
 
     def run(self):
         self.packet = self.comm.communicate(PAS5211MsgGetOltVersion())
-        self.packet.show()
         if self.packet is not None:
+            self.packet.show()
             self.completed = True
         return self.completed
 
     def transition(self):
         if self.completed:
             return Connected(self.comm)
+        else:
+            return self
+
+    def state(self):
+        return States.FETCH_VERSION
 
     def value(self):
         # TODO return a nicer value than the packet.
@@ -121,6 +158,9 @@
     def disconnect(self):
         raise NotImplementedError()
 
+    def abandon(self):
+        return False
+
 
 """
 OLT is in connected State
@@ -130,14 +170,22 @@
         self.comm = pas_comm
         self.completed = False
         self.packet = None
+        self.scheduled = False
         self.scheduledTask = task.LoopingCall(self.keepalive)
 
     def run(self):
-        self.scheduledTask.start(1.0)
+        if not self.scheduled:
+            self.scheduled = True
+            self.scheduledTask.start(1.0)
 
     def transition(self):
         if self.completed:
             return Disconnected(self.comm)
+        else:
+            return self
+
+    def state(self):
+        return States.CONNECTED
 
     def value(self):
         # TODO return a nicer value than the packet.
@@ -151,10 +199,17 @@
             log.info('OLT has been disconnected')
             return
         self.packet = self.comm.communicate(PAS5211MsgGetOltVersion())
-        self.packet.show()
         if self.packet is None:
             self.completed = True
+        else:
+            self.packet.show()
 
     def disconnect(self):
         print "Disconnecting OLT"
-        self.scheduledTask.stop()
+        if self.scheduled:
+            self.completed = True
+            self.scheduledTask.stop()
+        return self.transition()
+
+    def abandon(self):
+        return False
\ No newline at end of file