Introduce the openolt_data_model module.
A voltha adapter maintains its data model in KV store.
In most cases the interaction with the KV store's
data model is not direct but via the adapter_agent.
There is a fair amount of boiler-plate code in the
adapter related to the interaction with adapter_agent.
Most of this is going to change from voltha 1.x to 2.0.
This, and subsequent related commits, aim to abstract
out the adapter_agent interface in the openolt_data_model.
The resulting de-cluttered logic of the adapter will
be more amenable to re-use in the porting to 2.0.
Change-Id: Ic0d7223db2a6713bae7a0c953d11b1977759fab6
diff --git a/voltha/adapters/openolt/openolt.py b/voltha/adapters/openolt/openolt.py
index 995be78..814c26a 100644
--- a/voltha/adapters/openolt/openolt.py
+++ b/voltha/adapters/openolt/openolt.py
@@ -35,6 +35,7 @@
from voltha.adapters.openolt.openolt_bw import OpenOltBW
from voltha.adapters.openolt.openolt_platform import OpenOltPlatform
from voltha.adapters.openolt.openolt_resource_manager import OpenOltResourceMgr
+from voltha.adapters.openolt.openolt_data_model import OpenOltDataModel
_ = third_party
log = structlog.get_logger()
@@ -79,6 +80,7 @@
self.interface = registry('main').get_args().interface
self.logical_device_id_to_root_device_id = dict()
self.num_devices = 0
+ self.data_model = OpenOltDataModel(adapter_agent)
def start(self):
log.info('started', interface=self.interface)
@@ -109,6 +111,7 @@
kwargs = {
'support_classes': OpenOltDefaults['support_classes'],
+ 'data_model': self.data_model,
'adapter_agent': self.adapter_agent,
'device': device,
'device_num': self.num_devices + 1
diff --git a/voltha/adapters/openolt/openolt_data_model.py b/voltha/adapters/openolt/openolt_data_model.py
new file mode 100644
index 0000000..14903ae
--- /dev/null
+++ b/voltha/adapters/openolt/openolt_data_model.py
@@ -0,0 +1,163 @@
+#
+# Copyright 2019 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.
+#
+import structlog
+import socket
+from voltha.adapters.openolt.openolt_utils import OpenoltUtils
+from voltha.protos.device_pb2 import Port
+from voltha.protos.openflow_13_pb2 import OFPPS_LIVE, OFPPF_FIBER, \
+ OFPPS_LINK_DOWN, OFPPF_1GB_FD, OFPC_PORT_STATS, OFPC_TABLE_STATS, \
+ OFPC_FLOW_STATS, OFPC_GROUP_STATS, ofp_port, ofp_port_stats, ofp_desc, \
+ ofp_switch_features
+from voltha.core.logical_device_agent import mac_str_to_tuple
+from voltha.protos.logical_device_pb2 import LogicalPort
+from voltha.protos.common_pb2 import OperStatus, ConnectStatus
+from voltha.protos.logical_device_pb2 import LogicalDevice
+from voltha.registry import registry
+
+
+class OpenOltDataModel(object):
+ log = structlog.get_logger()
+
+ def __init__(self, adapter_agent):
+ self.adapter_agent = adapter_agent
+ self.log = structlog.get_logger()
+
+ def create_logical_device(self, device_id, device_info):
+ dpid = device_info.device_id
+ serial_number = device_info.device_serial_number
+
+ device = self.adapter_agent.get_device(device_id)
+ host_and_port = device.host_and_port
+
+ if dpid is None or dpid == '':
+ uri = host_and_port.split(":")[0]
+ try:
+ socket.inet_pton(socket.AF_INET, uri)
+ dpid = '00:00:' + OpenoltUtils.ip_hex(uri)
+ except socket.error:
+ # this is not an IP
+ dpid = OpenoltUtils.str_to_mac(uri)
+
+ self.log.info('creating-openolt-logical-device', dp_id=dpid,
+ serial_number=serial_number)
+
+ hw_desc = device_info.model
+ if device_info.hardware_version:
+ hw_desc += '-' + device_info.hardware_version
+
+ # Create logical OF device
+ ld = LogicalDevice(
+ root_device_id=device_id,
+ switch_features=ofp_switch_features(
+ n_buffers=256, # TODO fake for now
+ n_tables=2, # TODO ditto
+ capabilities=( # TODO and ditto
+ OFPC_FLOW_STATS
+ | OFPC_TABLE_STATS
+ | OFPC_PORT_STATS
+ | OFPC_GROUP_STATS
+ )
+ ),
+ desc=ofp_desc(
+ serial_num=serial_number
+ )
+ )
+ ld_init = self.adapter_agent.create_logical_device(ld,
+ dpid=dpid)
+
+ device = self.adapter_agent.get_device(device_id)
+ device.serial_number = serial_number
+ self.adapter_agent.update_device(device)
+
+ self.log.info('created-openolt-logical-device',
+ logical_device_id=ld_init.id)
+
+ return ld_init.id
+
+ def disable_logical_device(self, device_id):
+
+ oper_state = OperStatus.UNKNOWN
+ connect_state = ConnectStatus.UNREACHABLE
+
+ device = self.adapter_agent.get_device(device_id)
+
+ logical_device_id = device.parent_id
+
+ child_devices = self.adapter_agent.get_child_devices(device_id)
+ for onu_device in child_devices:
+ onu_adapter_agent = \
+ registry('adapter_loader').get_agent(onu_device.adapter)
+ onu_adapter_agent.update_interface(onu_device,
+ {'oper_state': 'down'})
+ self.onu_ports_down(onu_device, oper_state)
+
+ # Children devices
+ self.adapter_agent.update_child_devices_state(
+ device_id, oper_status=oper_state,
+ connect_status=connect_state)
+ # Device Ports
+ device_ports = self.adapter_agent.get_ports(device_id,
+ Port.ETHERNET_NNI)
+ logical_ports_ids = [port.label for port in device_ports]
+ device_ports += self.adapter_agent.get_ports(device_id,
+ Port.PON_OLT)
+
+ for port in device_ports:
+ port.oper_status = oper_state
+ self.adapter_agent.add_port(device_id, port)
+
+ # Device logical port
+ for logical_port_id in logical_ports_ids:
+ logical_port = self.adapter_agent.get_logical_port(
+ logical_device_id, logical_port_id)
+ logical_port.ofp_port.state = OFPPS_LINK_DOWN
+ self.adapter_agent.update_logical_port(self.logical_device_id,
+ logical_port)
+ device.oper_status = oper_state
+ device.connect_status = connect_state
+ self.adapter_agent.update_device(device)
+
+ def add_logical_port(self, logical_device_id, device_id, port_no, intf_id,
+ oper_state):
+ self.log.info('adding-logical-port', port_no=port_no)
+
+ label = OpenoltUtils.port_name(port_no, Port.ETHERNET_NNI)
+
+ cap = OFPPF_1GB_FD | OFPPF_FIBER
+ curr_speed = OFPPF_1GB_FD
+ max_speed = OFPPF_1GB_FD
+
+ if oper_state == OperStatus.ACTIVE:
+ of_oper_state = OFPPS_LIVE
+ else:
+ of_oper_state = OFPPS_LINK_DOWN
+
+ ofp = ofp_port(
+ port_no=port_no,
+ hw_addr=mac_str_to_tuple(
+ OpenoltUtils.make_mac_from_port_no(port_no)),
+ name=label, config=0, state=of_oper_state, curr=cap,
+ advertised=cap, peer=cap, curr_speed=curr_speed,
+ max_speed=max_speed)
+
+ ofp_stats = ofp_port_stats(port_no=port_no)
+
+ logical_port = LogicalPort(
+ id=label, ofp_port=ofp, device_id=device_id,
+ device_port_no=port_no, root_port=True,
+ ofp_port_stats=ofp_stats)
+
+ self.adapter_agent.add_logical_port(logical_device_id, logical_port)
diff --git a/voltha/adapters/openolt/openolt_device.py b/voltha/adapters/openolt/openolt_device.py
index 318d9e1..c7fc9d9 100644
--- a/voltha/adapters/openolt/openolt_device.py
+++ b/voltha/adapters/openolt/openolt_device.py
@@ -16,7 +16,6 @@
import threading
import binascii
import grpc
-import socket
import structlog
import time
from twisted.internet import reactor
@@ -25,17 +24,10 @@
from voltha.protos.device_pb2 import Port, Device
from voltha.protos.common_pb2 import OperStatus, AdminState, ConnectStatus
-from voltha.protos.logical_device_pb2 import LogicalDevice
-from voltha.protos.openflow_13_pb2 import OFPPS_LIVE, OFPPF_FIBER, \
- OFPPS_LINK_DOWN, OFPPF_1GB_FD, OFPC_GROUP_STATS, OFPC_PORT_STATS, \
- OFPC_TABLE_STATS, OFPC_FLOW_STATS, ofp_switch_features, ofp_port, \
- ofp_port_stats, ofp_desc
-from voltha.protos.logical_device_pb2 import LogicalPort
-from voltha.core.logical_device_agent import mac_str_to_tuple
+from voltha.protos.openflow_13_pb2 import OFPPS_LINK_DOWN
from voltha.registry import registry
from voltha.adapters.openolt.protos import openolt_pb2_grpc, openolt_pb2
from voltha.adapters.openolt.openolt_utils import OpenoltUtils
-
from voltha.extensions.alarms.onu.onu_discovery_alarm import OnuDiscoveryAlarm
@@ -84,6 +76,7 @@
self.admin_state = "up"
+ self.data_model = kwargs['data_model']
self.adapter_agent = kwargs['adapter_agent']
self.device_num = kwargs['device_num']
device = kwargs['device']
@@ -135,55 +128,6 @@
self.go_state_init()
- def create_logical_device(self, device_info):
- dpid = device_info.device_id
- serial_number = device_info.device_serial_number
-
- if dpid is None or dpid == '':
- uri = self.host_and_port.split(":")[0]
- try:
- socket.inet_pton(socket.AF_INET, uri)
- dpid = '00:00:' + OpenoltUtils.ip_hex(uri)
- except socket.error:
- # this is not an IP
- dpid = OpenoltUtils.str_to_mac(uri)
-
- self.log.info('creating-openolt-logical-device', dp_id=dpid,
- serial_number=serial_number)
-
- hw_desc = device_info.model
- if device_info.hardware_version:
- hw_desc += '-' + device_info.hardware_version
-
- # Create logical OF device
- ld = LogicalDevice(
- root_device_id=self.device_id,
- switch_features=ofp_switch_features(
- n_buffers=256, # TODO fake for now
- n_tables=2, # TODO ditto
- capabilities=( # TODO and ditto
- OFPC_FLOW_STATS
- | OFPC_TABLE_STATS
- | OFPC_PORT_STATS
- | OFPC_GROUP_STATS
- )
- ),
- desc=ofp_desc(
- serial_num=serial_number
- )
- )
- ld_init = self.adapter_agent.create_logical_device(ld,
- dpid=dpid)
-
- device = self.adapter_agent.get_device(self.device_id)
- device.serial_number = serial_number
- self.adapter_agent.update_device(device)
-
- self.log.info('created-openolt-logical-device',
- logical_device_id=ld_init.id)
-
- return ld_init.id
-
def do_state_init(self, event):
# Initialize gRPC
self.channel = grpc.insecure_channel(self.host_and_port)
@@ -222,8 +166,8 @@
if self.logical_device_id is None:
# first time connect to olt
- self.logical_device_id = self.create_logical_device(
- self.device_info)
+ self.logical_device_id = self.data_model.create_logical_device(
+ self.device_id, self.device_info)
else:
# reconnect to olt (e.g. olt reboot)
# TODO - Update logical device with new device_info
@@ -270,49 +214,8 @@
def do_state_down(self, event):
self.log.debug("do_state_down")
- oper_state = OperStatus.UNKNOWN
- connect_state = ConnectStatus.UNREACHABLE
- # Propagating to the children
-
- # Children ports
- child_devices = self.adapter_agent.get_child_devices(self.device_id)
- for onu_device in child_devices:
- onu_adapter_agent = \
- registry('adapter_loader').get_agent(onu_device.adapter)
- onu_adapter_agent.update_interface(onu_device,
- {'oper_state': 'down'})
- self.onu_ports_down(onu_device, oper_state)
-
- # Children devices
- self.adapter_agent.update_child_devices_state(
- self.device_id, oper_status=oper_state,
- connect_status=connect_state)
- # Device Ports
- device_ports = self.adapter_agent.get_ports(self.device_id,
- Port.ETHERNET_NNI)
- logical_ports_ids = [port.label for port in device_ports]
- device_ports += self.adapter_agent.get_ports(self.device_id,
- Port.PON_OLT)
-
- for port in device_ports:
- port.oper_status = oper_state
- self.adapter_agent.add_port(self.device_id, port)
-
- # Device logical port
- for logical_port_id in logical_ports_ids:
- logical_port = self.adapter_agent.get_logical_port(
- self.logical_device_id, logical_port_id)
- logical_port.ofp_port.state = OFPPS_LINK_DOWN
- self.adapter_agent.update_logical_port(self.logical_device_id,
- logical_port)
-
- # Device
- device = self.adapter_agent.get_device(self.device_id)
- device.oper_status = oper_state
- device.connect_status = connect_state
-
- reactor.callLater(2, self.adapter_agent.update_device, device)
+ self.data_model.disable_logical_device(self.device_id)
def post_down(self, event):
self.log.debug('post_down')
@@ -406,13 +309,6 @@
self.log.warn('unknown indication type')
def olt_indication(self, olt_indication):
- '''
- if self.admin_state is "up":
- if olt_indication.oper_state == "up":
- self.go_state_up()
- elif olt_indication.oper_state == "down":
- self.go_state_down()
- '''
if olt_indication.oper_state == "up":
self.go_state_up()
elif olt_indication.oper_state == "down":
@@ -447,8 +343,10 @@
port_no, label = self.add_port(intf_oper_indication.intf_id,
Port.ETHERNET_NNI, oper_state)
self.log.debug("int_oper_indication", port_no=port_no, label=label)
- self.add_logical_port(port_no, intf_oper_indication.intf_id,
- oper_state)
+ self.data_model.add_logical_port(self.logical_device_id,
+ self.device_id, port_no,
+ intf_oper_indication.intf_id,
+ oper_state)
elif intf_oper_indication.type == "pon":
# FIXME - handle PON oper state change
@@ -831,38 +729,6 @@
admin_state=AdminState.ENABLED
)
- def add_logical_port(self, port_no, intf_id, oper_state):
- self.log.info('adding-logical-port', port_no=port_no)
-
- label = OpenoltUtils.port_name(port_no, Port.ETHERNET_NNI)
-
- cap = OFPPF_1GB_FD | OFPPF_FIBER
- curr_speed = OFPPF_1GB_FD
- max_speed = OFPPF_1GB_FD
-
- if oper_state == OperStatus.ACTIVE:
- of_oper_state = OFPPS_LIVE
- else:
- of_oper_state = OFPPS_LINK_DOWN
-
- ofp = ofp_port(
- port_no=port_no,
- hw_addr=mac_str_to_tuple(
- OpenoltUtils.make_mac_from_port_no(port_no)),
- name=label, config=0, state=of_oper_state, curr=cap,
- advertised=cap, peer=cap, curr_speed=curr_speed,
- max_speed=max_speed)
-
- ofp_stats = ofp_port_stats(port_no=port_no)
-
- logical_port = LogicalPort(
- id=label, ofp_port=ofp, device_id=self.device_id,
- device_port_no=port_no, root_port=True,
- ofp_port_stats=ofp_stats)
-
- self.adapter_agent.add_logical_port(self.logical_device_id,
- logical_port)
-
def add_port(self, intf_id, port_type, oper_status):
port_no = self.platform.intf_id_to_port_no(intf_id, port_type)