blob: 91d85bf909aec3df6c6007a6a3d673524ae708e4 [file] [log] [blame]
#
# Copyright 2016 the original author or authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
"""
Base OLT State machine class
"""
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
# TODO convert to scapy automata
class State(object):
def __init__(self):
pass
"""
Attempt an operation towards the OLT
"""
def run(self):
raise NotImplementedError()
"""
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):
raise NotImplementedError()
"""
Sends a message to this olt
"""
def send_msg(self, msg):
raise NotImplementedError()
"""
Disconnected an OLT.
"""
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, 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())
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.
return self.packet
def send_msg(self, msg):
raise NotImplementedError()
def disconnect(self):
pass
def abandon(self):
return self.attempt > self.retry
"""
Fetches the OLT version
"""
class Fetch_Version(State):
def __init__(self, pas_comm):
self.comm = pas_comm
self.completed = False
self.packet = None
def run(self):
self.packet = self.comm.communicate(PAS5211MsgGetOltVersion())
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.
return self.packet
def send_msg(self, msg):
raise NotImplementedError()
def disconnect(self):
raise NotImplementedError()
def abandon(self):
return False
"""
OLT is in connected State
"""
class Connected(State):
def __init__(self, pas_comm):
self.comm = pas_comm
self.completed = False
self.packet = None
self.scheduled = False
self.scheduledTask = task.LoopingCall(self.keepalive)
def run(self):
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.
return self.packet
def send_msg(self, msg):
return self.comm.communicate(msg)
def keepalive(self):
if self.completed:
log.info('OLT has been disconnected')
return
self.packet = self.comm.communicate(PAS5211MsgGetOltVersion())
if self.packet is None:
self.completed = True
def disconnect(self):
print "Disconnecting OLT"
if self.scheduled:
self.completed = True
self.scheduledTask.stop()
return self.transition()
def abandon(self):
return False