Adds support for BBF WT-385 xPON model:
VOL-151: Framework for OLT PON Configuration Parameters
VOL-152: Framework for ONU Configuration Parameters
VOL-220: Support configuration(Create/Read/Delete) of Channel-Group,
Channel-Partition, Channel-Pair & Channel-Termination Objects
for XGS-PON
Change-Id: I992a4e03e6e7b021d7aa9a49a5f8466876c8f07c
diff --git a/cli/main.py b/cli/main.py
index 327f122..a05041a 100755
--- a/cli/main.py
+++ b/cli/main.py
@@ -29,6 +29,7 @@
from simplejson import dumps
from cli.device import DeviceCli
+from cli.xpon import XponCli
from cli.alarm_filters import AlarmFiltersCli
from cli.logical_device import LogicalDeviceCli
from cli.table import print_pb_list_as_table
@@ -241,6 +242,15 @@
if d.startswith(text)]
return completions
+ def do_xpon(self, line):
+ """xpon <optional> [device_ID] - Enter xpon level command mode"""
+ device_id = line.strip()
+ if not device_id:
+ sub = XponCli(self.get_channel, "")
+ else:
+ sub = XponCli(self.get_channel, device_id)
+ sub.cmdloop()
+
def do_pdb(self, line):
"""Launch PDB debug prompt in CLI (for CLI development)"""
from pdb import set_trace
diff --git a/cli/xpon.py b/cli/xpon.py
new file mode 100644
index 0000000..61b235b
--- /dev/null
+++ b/cli/xpon.py
@@ -0,0 +1,1157 @@
+#!/usr/bin/env python
+#
+# 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.
+#
+
+"""
+XPon level CLI commands
+"""
+from optparse import make_option
+from cmd2 import Cmd, options
+from simplejson import dumps
+
+from google.protobuf.empty_pb2 import Empty
+from cli.table import print_pb_as_table, print_pb_list_as_table
+from cli.utils import print_flows, pb2dict
+from voltha.protos import third_party
+from voltha.protos.bbf_fiber_base_pb2 import \
+ AllChannelgroupConfig, ChannelgroupConfig, \
+ AllChannelpairConfig, ChannelpairConfig, \
+ AllChannelpartitionConfig, ChannelpartitionConfig, \
+ AllChannelterminationConfig, ChannelterminationConfig, \
+ AllOntaniConfig, OntaniConfig, AllVOntaniConfig , \
+ VOntaniConfig, AllVEnetConfig , VEnetConfig
+
+_ = third_party
+from voltha.protos import voltha_pb2, bbf_fiber_types_pb2, ietf_interfaces_pb2
+import sys
+from google.protobuf.json_format import MessageToDict
+
+# Since proto3 won't send fields that are set to 0/false/"" any object that
+# might have those values set in them needs to be replicated here such that the
+# fields can be adequately
+
+class XponCli(Cmd):
+
+ def __init__(self, get_channel, device_id):
+ Cmd.__init__(self)
+ self.get_channel = get_channel
+ self.device_id = device_id
+ self.prompt = '(' + self.colorize(
+ self.colorize('voltha-xpon {}'.format(device_id), 'green'), 'bold') + ') '
+
+ def cmdloop(self):
+ self._cmdloop()
+
+ def get_interface_based_on_device(self):
+ stub = voltha_pb2.VolthaLocalServiceStub(self.get_channel())
+ temp_list = []
+ cg_list = []
+ cpart_list = []
+ cp_list = []
+ vont_list = []
+ ont_list = []
+ v_enet_list = []
+ ct = stub.GetAllChannelterminationConfig(voltha_pb2.ID(id=self.device_id))
+ cps = stub.GetAllChannelpairConfig(Empty()).channelpair_config
+ cparts = stub.GetAllChannelpartitionConfig(Empty()).channelpartition_config
+ cgs = stub.GetAllChannelgroupConfig(Empty()).channelgroup_config
+ onts = stub.GetAllOntaniConfig(Empty()).ontani_config
+ vonts = stub.GetAllVOntaniConfig(Empty()).v_ontani_config
+ venets = stub.GetAllVEnetConfig(Empty()).v_enet_config
+
+ for cterm in ct.channeltermination_config:
+ temp_list.append(cterm.data.channelpair_ref)
+ for cp in cps:
+ if cp.name in temp_list:
+ cp_list.append(cp)
+ temp_list = []
+
+ for cp in cp_list:
+ temp_list.append(cp.data.channelpartition_ref)
+ for cpart in cparts:
+ if cpart.name in temp_list:
+ cpart_list.append(cpart)
+ temp_list = []
+
+ for cpart in cpart_list:
+ temp_list.append(cpart.data.channelgroup_ref)
+ for cg in cgs:
+ if cg.name in temp_list:
+ cg_list.append(cg)
+ temp_list = []
+
+ for vont in vonts:
+ if vont.data.parent_ref in cpart_list or \
+ vont.data.preferred_chanpair in cp_list:
+ vont_list.append(vont)
+
+ for ont in onts:
+ if ont.name in vont_list:
+ ont_list.append(ont)
+ temp_list.append(ont.name)
+
+ for venet in venets:
+ if venet.data.v_ontani_ref in temp_list:
+ v_enet_list.append(venet)
+ temp_list = []
+
+ return cg_list, cpart_list, cp_list, ct.channeltermination_config, vont_list, ont_list, v_enet_list
+
+ do_exit = Cmd.do_quit
+
+ def do_quit(self, line):
+ return self._STOP_AND_EXIT
+
+ def do_show(self, line):
+ """Show detailed information of each interface based on device ID or all interfaces"""
+ stub = voltha_pb2.VolthaLocalServiceStub(self.get_channel())
+ if line.strip():
+ self.device_id = line.strip()
+ if self.device_id:
+ cg, cpart, cp, ct, vont, ont, venet = self.get_interface_based_on_device()
+ print_pb_list_as_table("Channel Groups for device ID = {}:".format(self.device_id),
+ cg, {}, self.poutput)
+ print_pb_list_as_table("Channel Partitions for device ID = {}:".format(self.device_id),
+ cpart, {}, self.poutput)
+ print_pb_list_as_table("Channel Pairs: for device ID = {}:".format(self.device_id),
+ cp, {}, self.poutput)
+ print_pb_list_as_table("Channel Terminations for device ID = {}:".format(self.device_id),
+ ct, {}, self.poutput)
+ print_pb_list_as_table("VOnt Anis for device ID = {}:".format(self.device_id),
+ vont, {}, self.poutput)
+ print_pb_list_as_table("Ont Anis for device ID = {}:".format(self.device_id),
+ ont, {}, self.poutput)
+ print_pb_list_as_table("VEnets for device ID = {}:".format(self.device_id),
+ venet, {}, self.poutput)
+ else:
+ interface = stub.GetAllChannelgroupConfig(Empty())
+ print_pb_list_as_table("Channel Groups:",
+ interface.channelgroup_config,
+ {}, self.poutput)
+ interface = stub.GetAllChannelpartitionConfig(Empty())
+ print_pb_list_as_table("Channel Partitions:",
+ interface.channelpartition_config,
+ {}, self.poutput)
+ interface = stub.GetAllChannelpairConfig(Empty())
+ print_pb_list_as_table("Channel Pairs:",
+ interface.channelpair_config,
+ {}, self.poutput)
+ devices = stub.ListDevices(Empty())
+ for d in devices.items:
+ interface = stub.GetAllChannelterminationConfig(voltha_pb2.ID(id=d.id))
+ print_pb_list_as_table("Channel Terminations for device ID = {}:".format(d.id),
+ interface.channeltermination_config,
+ {}, self.poutput)
+ interface = stub.GetAllVOntaniConfig(Empty())
+ print_pb_list_as_table("VOnt Anis:",
+ interface.v_ontani_config,
+ {}, self.poutput)
+ interface = stub.GetAllOntaniConfig(Empty())
+ print_pb_list_as_table("Ont Anis:",
+ interface.ontani_config,
+ {}, self.poutput)
+ interface = stub.GetAllVEnetConfig(Empty())
+ print_pb_list_as_table("VEnets:",
+ interface.v_enet_config,
+ {}, self.poutput)
+
+ def help_channel_group(self):
+ self.poutput(
+'''
+channel_group [get | create | update | delete] [-n <name>] [-d <description>] [-a <admin state>]
+ [-l <link up down trap enable type>] [-p <polling period>] [-s <system id>]
+ [-r <raman mitigation>]
+
+get: displays existing channel groups
+ Required flags: None
+create: creates channel group with the parameters specified with -n, -d, -a, -l, -p, -s and -r.
+ Required flags: <name>
+update: updates existing channel group specified with parameter -n by changing its parameter values
+ specified with -d, -a, -l, -p, -s and -r.
+ Required flags: <name>
+delete: deletes channel group specified with parameter -n.
+ Required flags: <name>
+
+-n: <string> name of channel group.
+-d: <string> description of channel group.
+-a: <string> admin state of channel group.
+-l: <enum> link up down trap enable type.
+-p: <int> polling period for channel group.
+-s: <string> system id for channel group.
+-r: <enum> raman mitigation for channel group.
+
+Example:
+
+channel_group create -n cg-1 -a up -p 100 -s 000000 -r raman_none
+'''
+ )
+
+ @options([
+ make_option('-n', '--name', action="store", dest='name', type='string',
+ help='name of channel group', default=None),
+ make_option('-d', '--description', action="store", dest='description',
+ type='string', help='description of channel group', default=None),
+ make_option('-a', '--admin_state', action="store", dest='enabled', type='string',
+ help='admin state of channel group', default=None),
+ make_option('-l', '--trap', action="store", dest='link_up_down_trap_enable',
+ type='string', help='link up down trap enable type', default=None),
+ make_option('-p', '--pp', action='store', dest='polling_period',
+ type='int', help='polling period of channel group', default=None),
+ make_option('-s', '--sid', action='store', dest='system_id',
+ type='string', help='system id of channel group', default=None),
+ make_option('-r', '--rm', action='store', dest='raman_mitigation',
+ type='string', help='raman mitigation of channel group', default=None),
+ ])
+
+ def do_channel_group(self, line, opts):
+ """channel group get, create -flags <attributes>, update -flags <attributes>, delete -n <name>"""
+ # Ensure that a valid sub-command was provided
+ if line.strip() not in {"get", "create", "update", "delete"}:
+ self.poutput(self.colorize('Error: ', 'red') + \
+ self.colorize(self.colorize(line.strip(), 'blue'),
+ 'bold') + ' is not recognized')
+ return
+
+ stub = voltha_pb2.VolthaLocalServiceStub(self.get_channel())
+
+ if line.strip() == "get":
+ if self.device_id:
+ cg, cpart, cp, ct, vont, ont, venet = self.get_interface_based_on_device()
+ print_pb_list_as_table("Channel Groups for device ID = {}:".format(self.device_id),
+ cg, {}, self.poutput)
+ else:
+ interface = stub.GetAllChannelgroupConfig(Empty())
+ print_pb_list_as_table("Channel Groups:",
+ interface.channelgroup_config,
+ {}, self.poutput)
+ return
+ #if not opts.name:
+ # self.poutput(self.colorize('Error: ', 'red') + \
+ # self.colorize(self.colorize('Name is required parameter', 'blue'),
+ # 'bold'))
+ # return
+ #if interface_instance:
+ # self.poutput(self.colorize('Unable. Please commit or reset: ', 'yellow') + \
+ # self.colorize(interface_instance.name, 'blue'))
+ # return
+ interface_instance = ChannelgroupConfig(name = opts.name)
+ interface_instance.interface.name = opts.name
+ if opts.description:
+ interface_instance.interface.description = opts.description
+ interface_instance.interface.type = "channelgroup"
+ if opts.enabled:
+ if opts.enabled == "up":
+ interface_instance.interface.enabled = True
+ elif opts.enabled == "down":
+ interface_instance.interface.enabled = False
+ else:
+ self.poutput(self.colorize('Error: ', 'red') + \
+ self.colorize(self.colorize('Invalid admin state parameter for channel group', 'blue'),
+ 'bold'))
+ return
+ if opts.link_up_down_trap_enable:
+ types = ["trap_disabled", "trap_enabled"]
+ try:
+ assert opts.link_up_down_trap_enable in types, \
+ 'Invalid Enum value for Channel Group link up down trap enable type \'{}\''\
+ .format(opts.link_up_down_trap_enable)
+ interface_instance.interface.link_up_down_trap_enable = \
+ ietf_interfaces_pb2._INTERFACE_LINKUPDOWNTRAPENABLETYPE.values_by_name[opts.link_up_down_trap_enable.upper()].number
+ except AssertionError, e:
+ self.poutput(self.colorize('Error: ', 'red') + \
+ self.colorize(self.colorize(e.message, 'blue'),
+ 'bold'))
+ return
+
+ if opts.polling_period:
+ interface_instance.data.polling_period = opts.polling_period
+ if opts.raman_mitigation:
+ raman_mitigations = ["raman_none", "raman_miller", "raman_8b10b"]
+ try:
+ assert opts.raman_mitigation in raman_mitigations, \
+ 'Invalid Enum value for Channel Group raman mitigation \'{}\''.format(opts.raman_mitigation)
+ interface_instance.data.raman_mitigation = \
+ bbf_fiber_types_pb2._RAMANMITIGATIONTYPE.values_by_name[opts.raman_mitigation.upper()].number
+ except AssertionError, e:
+ self.poutput(self.colorize('Error: ', 'red') + \
+ self.colorize(self.colorize(e.message, 'blue'),
+ 'bold'))
+ return
+ if opts.system_id:
+ interface_instance.data.system_id = opts.system_id
+
+ if line.strip() == "create":
+ stub.CreateChannelgroup(interface_instance)
+ elif line.strip() == "update":
+ stub.UpdateChannelgroup(interface_instance)
+ elif line.strip() == "delete":
+ stub.DeleteChannelgroup(interface_instance)
+ return
+
+ def help_channel_partition(self):
+ self.poutput(
+'''
+channel_partition [get | create | update | delete] [-n <name>] [-d <description>] [-a <admin state>]
+ [-l <link up down trap enable type>] [-r <differential fiber distance>]
+ [-o <closest ont distance>] [-f <fec downstream>] [-m <multicast aes indicator>]
+ [-u <authentication method>] [-c <channel group reference>]
+
+get: displays existing channel partitions
+ Required flags: None
+create: creates channel partition with the parameters specified with -n, -d, -a, -l, -r, -o, -f, -m, -u and -c.
+ Required flags: <name>, <channel group reference>
+update: updates existing channel partition specified with parameter -n by changing its parameter values
+ specified with -d, -a, -l, -r, -o, -f, -m, -u and -c.
+ Required flags: <name>
+delete: deletes channel group specified with parameter -n.
+ Required flags: <name>
+
+-n: <string> name of channel partition.
+-d: <string> description of channel partition.
+-a: <string> admin state of channel partition.
+-l: <enum> link up down trap enable type.
+-r: <int> differential fiber distance.
+-o: <int> closest ont distance.
+-f: <bool> forward and error correction downstream.
+-m: <bool> multicast aes indicator of channel partition.
+-u: <enum> authentication method.
+-c: <string> channel group reference for this channel partition.
+
+Example:
+
+channel_partition create -n cpart-1-1 -a up -r 20 -o 0 -f false -m false -u serial_number -c cg-1
+'''
+ )
+
+ @options([
+ make_option('-n', '--name', action="store", dest='name', type='string',
+ help='name of channel partition', default=None),
+ make_option('-d', '--description', action="store", dest='description',
+ type='string', help='description of channel partition', default=None),
+ make_option('-a', '--admin_state', action="store", dest='enabled', type='string',
+ help='admin state of channel partition', default=None),
+ make_option('-l', '--trap', action="store", dest='link_up_down_trap_enable',
+ type='string', help='link up down trap enable type', default=None),
+ make_option('-r', '--diff_fib_dist', action='store', dest='differential_fiber_distance',
+ type='int', help='differential fiber distance', default=None),
+ make_option('-o', '--ont_dist', action='store', dest='closest_ont_distance',
+ type='int', help='closest ont distance', default=None),
+ make_option('-f', '--fec_ds', action='store', dest='fec_downstream',
+ type='string', help='forward and error correction downstream', default=None),
+ make_option('-m', '--mc_aes', action='store', dest='multicast_aes_indicator',
+ type='string', help='multicast aes indicator of channel partition', default=None),
+ make_option('-u', '--auth', action='store', dest='authentication_method',
+ type='string', help='authentication method', default=None),
+ make_option('-c', '--cg_ref', action='store', dest='channelgroup_ref',
+ type='string', help='channel group reference for this channel partition', default=None),
+ ])
+
+ def do_channel_partition(self, line, opts):
+ """channel partition get, create -flags <attributes>, update -flags <attributes>, delete -n <name>"""
+ # Ensure that a valid sub-command was provided
+ if line.strip() not in {"get", "create", "update", "delete"}:
+ self.poutput(self.colorize('Error: ', 'red') + \
+ self.colorize(self.colorize(line.strip(), 'blue'),
+ 'bold') + ' is not recognized')
+ return
+
+ stub = voltha_pb2.VolthaLocalServiceStub(self.get_channel())
+
+ if line.strip() == "get":
+ if self.device_id:
+ cg, cpart, cp, ct, vont, ont, venet = self.get_interface_based_on_device()
+ print_pb_list_as_table("Channel Partitions for device ID = {}:".format(self.device_id),
+ cpart, {}, self.poutput)
+ else:
+ interface = stub.GetAllChannelpartitionConfig(Empty())
+ print_pb_list_as_table("Channel Partitions:",
+ interface.channelpartition_config,
+ {}, self.poutput)
+ return
+
+ interface_instance = ChannelpartitionConfig(name = opts.name)
+ interface_instance.interface.name = opts.name
+ if opts.description:
+ interface_instance.interface.description = opts.description
+ interface_instance.interface.type = "channelpartition"
+ if opts.enabled:
+ if opts.enabled == "up":
+ interface_instance.interface.enabled = True
+ elif opts.enabled == "down":
+ interface_instance.interface.enabled = False
+ else:
+ self.poutput(self.colorize('Error: ', 'red') + \
+ self.colorize(self.colorize('Invalid admin state parameter for channel partition', 'blue'),
+ 'bold'))
+ return
+ if opts.link_up_down_trap_enable:
+ types = ["trap_disabled", "trap_enabled"]
+ try:
+ assert opts.link_up_down_trap_enable in types, \
+ 'Invalid Enum value for Channel Partition link up down trap enable type \'{}\''\
+ .format(opts.link_up_down_trap_enable)
+ interface_instance.interface.link_up_down_trap_enable = \
+ ietf_interfaces_pb2._INTERFACE_LINKUPDOWNTRAPENABLETYPE.values_by_name[opts.link_up_down_trap_enable.upper()].number
+ except AssertionError, e:
+ self.poutput(self.colorize('Error: ', 'red') + \
+ self.colorize(self.colorize(e.message, 'blue'),
+ 'bold'))
+ return
+
+ if opts.differential_fiber_distance:
+ interface_instance.data.differential_fiber_distance = opts.differential_fiber_distance
+ if opts.closest_ont_distance:
+ interface_instance.data.closest_ont_distance = opts.closest_ont_distance
+ if opts.fec_downstream:
+ if opts.fec_downstream == 'true':
+ interface_instance.data.fec_downstream = True
+ elif opts.fec_downstream == 'false':
+ interface_instance.data.fec_downstream = False
+ else:
+ m = 'Invalid boolean value for Channel Partition fec_downstream \'{}\''\
+ .format(opts.fec_downstream)
+ self.poutput(self.colorize('Error: ', 'red') + \
+ self.colorize(self.colorize(m, 'blue'),
+ 'bold'))
+ return
+ if opts.multicast_aes_indicator:
+ if opts.multicast_aes_indicator == 'true':
+ interface_instance.data.multicast_aes_indicator = True
+ elif opts.multicast_aes_indicator == 'false':
+ interface_instance.data.multicast_aes_indicator = False
+ else:
+ m = 'Invalid boolean value for Channel Partition multicast_aes_indicator \'{}\''\
+ .format(opts.multicast_aes_indicator)
+ self.poutput(self.colorize('Error: ', 'red') + \
+ self.colorize(self.colorize(m, 'blue'),
+ 'bold'))
+ return
+ if opts.authentication_method:
+ auth_method_types = ["serial_number", "loid", "registration_id", "omci", "dot1x"]
+ try:
+ assert opts.authentication_method in auth_method_types, \
+ 'Invalid Enum value for Channel Partition authentication method \'{}\''.format(opts.authentication_method)
+ interface_instance.data.authentication_method = \
+ bbf_fiber_types_pb2._AUTHMETHODTYPE.values_by_name[opts.authentication_method.upper()].number
+ except AssertionError, e:
+ self.poutput(self.colorize('Error: ', 'red') + \
+ self.colorize(self.colorize(e.message, 'blue'),
+ 'bold'))
+ return
+ if opts.channelgroup_ref:
+ interface_instance.data.channelgroup_ref = opts.channelgroup_ref
+
+ if line.strip() == "create":
+ stub.CreateChannelpartition(interface_instance)
+ elif line.strip() == "update":
+ stub.UpdateChannelpartition(interface_instance)
+ elif line.strip() == "delete":
+ stub.DeleteChannelpartition(interface_instance)
+ return
+
+ def help_channel_pair(self):
+ self.poutput(
+'''
+channel_pair [get | create | update | delete] [-n <name>] [-d <description>] [-a <admin state>]
+ [-l <link up down trap enable type>] [-r <channel pair line rate>]
+ [-t <channel pair type>] [-g <channel group reference>] [-i <gpon pon id interval>]
+ [-p <channel partition reference>] [-o <gpon pon id odn class>]
+
+get: displays existing channel pairs
+ Required flags: None
+create: creates channel pair with the parameters specified with -n, -d, -a, -l, -r, -t, -g, -i, -p and -o.
+ Required flags: <name>, <channel pair type>
+update: updates existing channel pair specified with parameter -n by changing its parameter values
+ specified with -d, -a, -l, -r, -t, -g, -i, -p and -o.
+ Required flags: <name>
+delete: deletes channel group specified with parameter -n.
+ Required flags: <name>
+
+-n: <string> name of channel pair.
+-d: <string> description of channel pair.
+-a: <string> admin state of channel pair.
+-l: <enum> link up down trap enable type.
+-r: <string> channel pair line rate.
+-t: <string> channel pair type.
+-g: <string> channel group reference.
+-i: <int> gpon pon id interval.
+-p: <string> channel partition reference.
+-o: <enum> gpon pon id odn class.
+
+Example:
+
+channel_pair create -n cp-1 -a up -r unplanned_cp_speed -t channelpair -g cg-1 -i 0 -p cpart-1-1 -o class_a
+'''
+ )
+
+ @options([
+ make_option('-n', '--name', action="store", dest='name', type='string',
+ help='name of channel pair', default=None),
+ make_option('-d', '--description', action="store", dest='description',
+ type='string', help='description of channel pair', default=None),
+ make_option('-a', '--admin_state', action="store", dest='enabled', type='string',
+ help='admin state of channel pair', default=None),
+ make_option('-l', '--trap', action="store", dest='link_up_down_trap_enable',
+ type='string', help='link up down trap enable type', default=None),
+ make_option('-r', '--cp_line_rate', action='store', dest='channelpair_linerate',
+ type='string', help='channel pair linerate', default=None),
+ make_option('-t', '--cp_type', action='store', dest='channelpair_type',
+ type='string', help='channel pair type', default=None),
+ make_option('-g', '--cg_ref', action='store', dest='channelgroup_ref',
+ type='string', help='channel group reference', default=None),
+ make_option('-i', '--interval', action='store', dest='gpon_ponid_interval',
+ type='int', help='gpon pon id interval', default=None),
+ make_option('-p', '--cpart_ref', action='store', dest='channelpartition_ref',
+ type='string', help='channel partition reference', default=None),
+ make_option('-o', '--odn_class', action='store', dest='gpon_ponid_odn_class',
+ type='string', help='gpon pon id odn class', default=None),
+ ])
+
+ def do_channel_pair(self, line, opts):
+ """channel pair get, create -flags <attributes>, update -flags <attributes>, delete -n <name>"""
+ # Ensure that a valid sub-command was provided
+ if line.strip() not in {"get", "create", "update", "delete"}:
+ self.poutput(self.colorize('Error: ', 'red') + \
+ self.colorize(self.colorize(line.strip(), 'blue'),
+ 'bold') + ' is not recognized')
+ return
+
+ stub = voltha_pb2.VolthaLocalServiceStub(self.get_channel())
+
+ if line.strip() == "get":
+ if self.device_id:
+ cg, cpart, cp, ct, vont, ont, venet = self.get_interface_based_on_device()
+ print_pb_list_as_table("Channel Pairs for device ID = {}:".format(self.device_id),
+ cp, {}, self.poutput)
+ else:
+ interface = stub.GetAllChannelpairConfig(Empty())
+ print_pb_list_as_table("Channel Pairs:",
+ interface.channelpair_config,
+ {}, self.poutput)
+ return
+
+ interface_instance = ChannelpairConfig(name = opts.name)
+ interface_instance.interface.name = opts.name
+ if opts.description:
+ interface_instance.interface.description = opts.description
+ interface_instance.interface.type = "channelpair"
+ if opts.enabled:
+ if opts.enabled == "up":
+ interface_instance.interface.enabled = True
+ elif opts.enabled == "down":
+ interface_instance.interface.enabled = False
+ else:
+ self.poutput(self.colorize('Error: ', 'red') + \
+ self.colorize(self.colorize('Invalid admin state parameter for channel pair', 'blue'),
+ 'bold'))
+ return
+ if opts.link_up_down_trap_enable:
+ types = ["trap_disabled", "trap_enabled"]
+ try:
+ assert opts.link_up_down_trap_enable in types, \
+ 'Invalid Enum value for Channel Pair link up down trap enable type \'{}\''\
+ .format(opts.link_up_down_trap_enable)
+ interface_instance.interface.link_up_down_trap_enable = \
+ ietf_interfaces_pb2._INTERFACE_LINKUPDOWNTRAPENABLETYPE.values_by_name[opts.link_up_down_trap_enable.upper()].number
+ except AssertionError, e:
+ self.poutput(self.colorize('Error: ', 'red') + \
+ self.colorize(self.colorize(e.message, 'blue'),
+ 'bold'))
+ return
+
+ if opts.channelpair_linerate:
+ interface_instance.data.channelpair_linerate = opts.channelpair_linerate
+ if opts.channelpair_type:
+ interface_instance.data.channelpair_type = opts.channelpair_type
+ if opts.channelgroup_ref:
+ interface_instance.data.channelgroup_ref = opts.channelgroup_ref
+ if opts.gpon_ponid_interval:
+ interface_instance.data.gpon_ponid_interval = opts.gpon_ponid_interval
+ if opts.channelpartition_ref:
+ interface_instance.data.channelpartition_ref = opts.channelpartition_ref
+ if opts.gpon_ponid_odn_class:
+ class_types = ["class_a", "class_b", "class_b_plus", "class_c", "class_c_plus", "class_auto"]
+ try:
+ assert opts.gpon_ponid_odn_class in class_types, \
+ 'Invalid enum value for Channel Pair gpon pon id odn class \'{}\''.format(opts.gpon_ponid_odn_class)
+ interface_instance.data.gpon_ponid_odn_class = \
+ bbf_fiber_types_pb2._PONIDODNCLASSTYPE.values_by_name[opts.gpon_ponid_odn_class.upper()].number
+ except AssertionError, e:
+ self.poutput(self.colorize('Error: ', 'red') + \
+ self.colorize(self.colorize(e.message, 'blue'),
+ 'bold'))
+ return
+
+ if line.strip() == "create":
+ stub.CreateChannelpair(interface_instance)
+ elif line.strip() == "update":
+ stub.UpdateChannelpair(interface_instance)
+ elif line.strip() == "delete":
+ stub.DeleteChannelpair(interface_instance)
+ return
+
+ def help_channel_termination(self):
+ self.poutput(
+'''
+channel_termination [get | create | update | delete] [-i <id>] [-n <name>]
+ [-d <description>] [-a <admin state>] [-l <link up down trap enable type>]
+ [-r <channel pair reference>] [-m <meant for type_b primary role>]
+ [-w <ngpon2 time wavelength division multiplexing admin label>]
+ [-p <ngpon2 ptp admin label>] [-s <xgs pon id>]
+ [-x <xgpon pon id>] [-g <gpon pon id>] [-t <pon tag>]
+ [-b <ber calc period>] [-l <location>] [-u <url to reach>]
+
+get: displays existing channel pairs
+ Required flags: None
+create: creates channel pair with the parameters specified with -i -n, -d, -a, -l, -r, -m, -w, -p, -s, -x, -g, -t, -b, -c and -u
+ Required flags: <id>, <name>
+update: updates existing channel termination specified with -i and -n parameters by changing
+ its parameter values specified with -d, -a, -l, -r, -m, -w, -p, -s, -x, -g, -b, -c, and -u
+ Required flags: <id>, <name>
+delete: deletes channel termination specified with parameter -i and -n.
+ Required flags: <id>, <name>
+
+-i: <string> device id.
+-n: <string> name of channel termination.
+-d: <string> description of channel termination.
+-a: <string> admin state of channel termination.
+-l: <enum> link up down trap enable type.
+-r: <string> channel pair reference for this channel termination.
+-m: <bool> meant for type_b primary role.
+-w: <int> ngpon2 time wavelength division multiplexing admin label.
+-p: <int> ngpon2 precision time protocol admin label.
+-s: <int> xgs pon id.
+-x: <int> xgpon pon id.
+-g: <string> gpon pon id.
+-t: <string> pon tag.
+-b: <int> bit error rate calculation period.
+-c: <string> location of channel termination.
+-u: <string> url to reach channel termination.
+
+Example:
+
+channel_termination create -i f90bb953f988 -n cterm-1 -a up -r cp-1 -m false -w 0 -p 0 -s 0 -x 0 -b 0 -c raleigh -u localhost
+
+'''
+ )
+
+ @options([
+ make_option('-i', '--id', action="store", dest='id', type='string',
+ help='device id', default=None),
+ make_option('-n', '--name', action="store", dest='name', type='string',
+ help='name of channel pair', default=None),
+ make_option('-d', '--description', action="store", dest='description',
+ type='string', help='description of channel termination', default=None),
+ make_option('-a', '--admin_state', action="store", dest='enabled', type='string',
+ help='admin state of channel termination', default=None),
+ make_option('-l', '--trap', action="store", dest='link_up_down_trap_enable',
+ type='string', help='link up down trap enable type', default=None),
+ make_option('-r', '--cp_ref', action='store', dest='channelpair_ref',
+ type='string', help='channel pair reference for this channel termination', default=None),
+ make_option('-m', '--type_b', action='store', dest='meant_for_type_b_primary_role',
+ type='string', help='meant for type_b primary role', default=None),
+ make_option('-w', '--t_w_d_m', action='store', dest='ngpon2_twdm_admin_label',
+ type='int', help='ngpon2 time wavelength division multiplexing admin label', default=None),
+ make_option('-p', '--ptp', action='store', dest='ngpon2_ptp_admin_label',
+ type='int', help='ngpon2 precision time protocol admin label', default=None),
+ make_option('-s', '--xgs', action='store', dest='xgs_ponid',
+ type='int', help='xgs pon id', default=None),
+ make_option('-x', '--xgpon', action='store', dest='xgpon_ponid',
+ type='int', help='xgpon pon id', default=None),
+ make_option('-g', '--gpon_pon', action='store', dest='gpon_ponid',
+ type='string', help='gpon pon id', default=None),
+ make_option('-t', '--pon', action='store', dest='pon_tag',
+ type='string', help='pon tag', default=None),
+ make_option('-b', '--ber', action='store', dest='ber_calc_period',
+ type='int', help='bit error rate calculation period', default=None),
+ make_option('-c', '--location', action='store', dest='location',
+ type='string', help='location of channel termination', default=None),
+ make_option('-u', '--url', action='store', dest='url_to_reach',
+ type='string', help='url to reach channel termination', default=None),
+ ])
+
+ def do_channel_termination(self, line, opts):
+ """channel termination get, create -flags <attributes>, update -flags <attributes>, delete -i <id> -n <name>"""
+ # Ensure that a valid sub-command was provided
+ if line.strip() not in {"get", "create", "update", "delete"}:
+ self.poutput(self.colorize('Error: ', 'red') + \
+ self.colorize(self.colorize(line.strip(), 'blue'),
+ 'bold') + ' is not recognized')
+ return
+
+ stub = voltha_pb2.VolthaLocalServiceStub(self.get_channel())
+
+ if line.strip() == "get":
+ if self.device_id:
+ cg, cpart, cp, ct, vont, ont, venet = self.get_interface_based_on_device()
+ print_pb_list_as_table("Channel Terminations for device ID = {}:".format(self.device_id),
+ ct, {}, self.poutput)
+ elif opts.id:
+ ct = stub.GetAllChannelterminationConfig(voltha_pb2.ID(id=opts.id)).channeltermination_config
+ print_pb_list_as_table("Channel Terminations for device ID = {}:".format(opts.id),
+ ct, {}, self.poutput)
+ else:
+ devices = stub.ListDevices(Empty())
+ for d in devices.items:
+ interface = stub.GetAllChannelterminationConfig(voltha_pb2.ID(id=d.id))
+ print_pb_list_as_table("Channel Terminations for device ID = {}:".format(d.id),
+ interface.channeltermination_config,
+ {}, self.poutput)
+ return
+
+ interface_instance = ChannelterminationConfig(id = opts.id, name = opts.name)
+ interface_instance.interface.name = opts.name
+ if opts.description:
+ interface_instance.interface.description = opts.description
+ interface_instance.interface.type = "channel-termination"
+ if opts.enabled:
+ if opts.enabled == "up":
+ interface_instance.interface.enabled = True
+ elif opts.enabled == "down":
+ interface_instance.interface.enabled = False
+ else:
+ self.poutput(self.colorize('Error: ', 'red') + \
+ self.colorize(self.colorize('Invalid admin state parameter for channel termination', 'blue'),
+ 'bold'))
+ return
+ if opts.link_up_down_trap_enable:
+ types = ["trap_disabled", "trap_enabled"]
+ try:
+ assert opts.link_up_down_trap_enable in types, \
+ 'Invalid Enum value for Channel Termination link up down trap enable type \'{}\''\
+ .format(opts.link_up_down_trap_enable)
+ interface_instance.interface.link_up_down_trap_enable = \
+ ietf_interfaces_pb2._INTERFACE_LINKUPDOWNTRAPENABLETYPE.values_by_name[opts.link_up_down_trap_enable.upper()].number
+ except AssertionError, e:
+ self.poutput(self.colorize('Error: ', 'red') + \
+ self.colorize(self.colorize(e.message, 'blue'),
+ 'bold'))
+ return
+
+ if opts.channelpair_ref:
+ interface_instance.data.channelpair_ref = opts.channelpair_ref
+ if opts.meant_for_type_b_primary_role:
+ if opts.meant_for_type_b_primary_role == 'true':
+ interface_instance.data.meant_for_type_b_primary_role = True
+ elif opts.meant_for_type_b_primary_role == 'false':
+ interface_instance.data.meant_for_type_b_primary_role = False
+ else:
+ m = 'Invalid boolean value for Channel Termination meant_for_type_b_primary_role \'{}\''\
+ .format(opts.meant_for_type_b_primary_role)
+ self.poutput(self.colorize('Error: ', 'red') + \
+ self.colorize(self.colorize(m, 'blue'),
+ 'bold'))
+ return
+ if opts.ngpon2_twdm_admin_label:
+ interface_instance.data.ngpon2_twdm_admin_label = opts.ngpon2_twdm_admin_label
+ if opts.ngpon2_ptp_admin_label:
+ interface_instance.data.ngpon2_ptp_admin_label = opts.ngpon2_ptp_admin_label
+ if opts.xgs_ponid:
+ interface_instance.data.xgs_ponid = opts.xgs_ponid
+ if opts.xgpon_ponid:
+ interface_instance.data.xgpon_ponid = opts.xgpon_ponid
+ if opts.gpon_ponid:
+ interface_instance.data.gpon_ponid = opts.gpon_ponid
+ if opts.pon_tag:
+ interface_instance.data.pon_tag = opts.pon_tag
+ if opts.ber_calc_period:
+ interface_instance.data.ber_calc_period = opts.ber_calc_period
+ if opts.location:
+ interface_instance.data.location = opts.location
+ if opts.url_to_reach:
+ interface_instance.data.url_to_reach = opts.url_to_reach
+
+ if line.strip() == "create":
+ stub.CreateChanneltermination(interface_instance)
+ elif line.strip() == "update":
+ stub.UpdateChanneltermination(interface_instance)
+ elif line.strip() == "delete":
+ stub.DeleteChanneltermination(interface_instance)
+ return
+
+ def help_vont_ani(self):
+ self.poutput(
+'''
+vont_ani [get | create | update | delete] [-n <name>] [-d <description>] [-a <admin state>]
+ [-l <link up down trap enable type>] [-p <parent reference>]
+ [-s <expected serial number>] [-i <expected registration id>]
+ [-r <preferred channel pair>] [-t <protection channel pair>]
+ [-u <upstream channel speed>] [-o <onu id>]
+
+get: displays existing vont anis
+ Required flags: None
+create: creates vont ani with the parameters specified with -n, -d, -a, -l, -p, -s, -i, -r, -t, -u and -o.
+ Required flags: <name>
+update: updates existing vont ani specified with parameter -n by changing its parameter values
+ specified with -d, -a, -l, -p, -s, -i, -r, -t, -u and -o.
+ Required flags: <name>
+delete: deletes vont ani specified with parameter -n.
+ Required flags: <name>
+
+-n: <string> name of vont ani.
+-d: <string> description of vont ani.
+-a: <string> admin state of vont ani.
+-l: <enum> link up down trap enable type.
+-p: <string> parent reference of vont ani must be type of channel partition.
+-s: <string> expected serial number of ONT.
+-i: <string> expected registration id of ONT.
+-r: <string> preferred channel pair must be type of channel pair.
+-t: <string> protection channel pair must be type of channel pair.
+-u: <int> upstream channel speed of traffic.
+-o <int> ONU id.
+
+Example:
+
+vont_ani create -n ontani-1-1-1 -a up -p cpart-1-1 -s ALCL00000001 -r cp-1 -u 0 -o 1
+'''
+ )
+
+ @options([
+ make_option('-n', '--name', action="store", dest='name', type='string',
+ help='name of vont ani', default=None),
+ make_option('-d', '--description', action="store", dest='description',
+ type='string', help='description of vont ani', default=None),
+ make_option('-a', '--admin_state', action="store", dest='enabled', type='string',
+ help='admin state of vont ani', default=None),
+ make_option('-l', '--trap', action="store", dest='link_up_down_trap_enable',
+ type='string', help='link up down trap enable type', default=None),
+ make_option('-p', '--parent_ref', action='store', dest='parent_ref',
+ type='string', help='parent reference of vont ani must be type of channel partition',
+ default=None),
+ make_option('-s', '--e_ser_num', action='store', dest='expected_serial_number',
+ type='string', help='expected serial number of ONT', default=None),
+ make_option('-i', '--e_reg_id', action='store', dest='expected_registration_id',
+ type='string', help='expected registration id of ONT', default=None),
+ make_option('-r', '--pref_cp', action='store', dest='preferred_chanpair',
+ type='string', help='preferred channel pair must be type of channel pair',
+ default=None),
+ make_option('-t', '--prot_cp', action='store', dest='protection_chanpair',
+ type='string', help='protection channel pair must be type of channel pair',
+ default=None),
+ make_option('-u', '--up_cs', action='store', dest='upstream_channel_speed',
+ type='int', help='upstream channel speed of traffic', default=None),
+ make_option('-o', '--onu_id', action='store', dest='onu_id',
+ type='int', help='onu id', default=None),
+ ])
+
+ def do_vont_ani(self, line, opts):
+ """vont ani get, create -flags <attributes>, update -flags <attributes>, delete -n <name>"""
+ # Ensure that a valid sub-command was provided
+ if line.strip() not in {"get", "create", "update", "delete"}:
+ self.poutput(self.colorize('Error: ', 'red') + \
+ self.colorize(self.colorize(line.strip(), 'blue'),
+ 'bold') + ' is not recognized')
+ return
+
+ stub = voltha_pb2.VolthaLocalServiceStub(self.get_channel())
+
+ if line.strip() == "get":
+ if self.device_id:
+ cg, cpart, cp, ct, vont, ont, venet = self.get_interface_based_on_device()
+ print_pb_list_as_table("VOnt Anis for device ID = {}:".format(self.device_id),
+ vont, {}, self.poutput)
+ else:
+ interface = stub.GetAllVOntaniConfig(Empty())
+ print_pb_list_as_table("VOnt Anis:",
+ interface.v_ontani_config,
+ {}, self.poutput)
+ return
+
+ interface_instance = VOntaniConfig(name = opts.name)
+ interface_instance.interface.name = opts.name
+ if opts.description:
+ interface_instance.interface.description = opts.description
+ interface_instance.interface.type = "v-ontani"
+ if opts.enabled:
+ if opts.enabled == "up":
+ interface_instance.interface.enabled = True
+ elif opts.enabled == "down":
+ interface_instance.interface.enabled = False
+ else:
+ self.poutput(self.colorize('Error: ', 'red') + \
+ self.colorize(self.colorize('Invalid admin state parameter for vont ani', 'blue'),
+ 'bold'))
+ return
+ if opts.link_up_down_trap_enable:
+ types = ["trap_disabled", "trap_enabled"]
+ try:
+ assert opts.link_up_down_trap_enable in types, \
+ 'Invalid Enum value for VOnt Ani link up down trap enable type \'{}\''\
+ .format(opts.link_up_down_trap_enable)
+ interface_instance.interface.link_up_down_trap_enable = \
+ ietf_interfaces_pb2._INTERFACE_LINKUPDOWNTRAPENABLETYPE.values_by_name[opts.link_up_down_trap_enable.upper()].number
+ except AssertionError, e:
+ self.poutput(self.colorize('Error: ', 'red') + \
+ self.colorize(self.colorize(e.message, 'blue'),
+ 'bold'))
+ return
+
+ if opts.parent_ref:
+ interface_instance.data.parent_ref = opts.parent_ref
+ if opts.expected_serial_number:
+ interface_instance.data.expected_serial_number = opts.expected_serial_number
+ if opts.expected_registration_id:
+ interface_instance.data.expected_registration_id = opts.expected_registration_id
+ if opts.preferred_chanpair:
+ interface_instance.data.preferred_chanpair = opts.preferred_chanpair
+ if opts.protection_chanpair:
+ interface_instance.data.protection_chanpair = opts.protection_chanpair
+ if opts.upstream_channel_speed:
+ interface_instance.data.upstream_channel_speed = opts.upstream_channel_speed
+ if opts.onu_id:
+ interface_instance.data.onu_id = opts.onu_id
+
+ if line.strip() == "create":
+ stub.CreateVOntani(interface_instance)
+ elif line.strip() == "update":
+ stub.UpdateVOntani(interface_instance)
+ elif line.strip() == "delete":
+ stub.DeleteVOntani(interface_instance)
+ return
+
+ def help_ont_ani(self):
+ self.poutput(
+'''
+ont_ani [get | create | update | delete] [-n <name>] [-d <description>] [-a <admin state>]
+ [-l <link up down trap enable type>] [-u <upstream fec indicator>]
+ [-m <management gem port aes indicator>]
+
+get: displays existing ont anis
+ Required flags: None
+create: creates ont ani with the parameters specified with -n, -d, -a, -l, -u and -m.
+ Required flags: <name>
+update: updates existing ont ani specified with parameter -n by changing its parameter values
+ specified with -d, -a, -l, -u and -m.
+ Required flags: <name>
+delete: deletes ont ani specified with parameter -n.
+ Required flags: <name>
+
+-n: <string> name of ont ani.
+-d: <string> description of ont ani.
+-a: <string> admin state of ont ani.
+-l: <enum> link up down trap enable type.
+-u: <bool> upstream traffic fec indicator.
+-m: <bool> management gem port aes indicator.
+
+Example:
+
+ont_ani create -n ontani-1-1-1 -a up -u true -m true
+'''
+ )
+
+ @options([
+ make_option('-n', '--name', action="store", dest='name', type='string',
+ help='name of ont ani', default=None),
+ make_option('-d', '--description', action="store", dest='description',
+ type='string', help='description of ont ani', default=None),
+ make_option('-a', '--admin_state', action="store", dest='enabled', type='string',
+ help='admin state of ont ani', default=None),
+ make_option('-l', '--trap', action="store", dest='link_up_down_trap_enable',
+ type='string', help='link up down trap enable type', default=None),
+ make_option('-u', '--up_fec', action='store', dest='upstream_fec_indicator',
+ type='string', help='upstream traffic fec indicator', default=None),
+ make_option('-m', '--maes', action='store', dest='mgnt_gemport_aes_indicator',
+ type='string', help='management gem port aes indicator', default=None),
+ ])
+
+ def do_ont_ani(self, line, opts):
+ """ont ani get, create -flags <attributes>, update -flags <attributes>, delete -n <name>"""
+ # Ensure that a valid sub-command was provided
+ if line.strip() not in {"get", "create", "update", "delete"}:
+ self.poutput(self.colorize('Error: ', 'red') + \
+ self.colorize(self.colorize(line.strip(), 'blue'),
+ 'bold') + ' is not recognized')
+ return
+
+ stub = voltha_pb2.VolthaLocalServiceStub(self.get_channel())
+
+ if line.strip() == "get":
+ if self.device_id:
+ cg, cpart, cp, ct, vont, ont, venet = self.get_interface_based_on_device()
+ print_pb_list_as_table("Ont Anis for device ID = {}:".format(self.device_id),
+ ont, {}, self.poutput)
+ else:
+ interface = stub.GetAllOntaniConfig(Empty())
+ print_pb_list_as_table("Ont Anis:",
+ interface.ontani_config,
+ {}, self.poutput)
+ return
+
+ interface_instance = OntaniConfig(name = opts.name)
+ interface_instance.interface.name = opts.name
+ if opts.description:
+ interface_instance.interface.description = opts.description
+ interface_instance.interface.type = "ontani"
+ if opts.enabled:
+ if opts.enabled == "up":
+ interface_instance.interface.enabled = True
+ elif opts.enabled == "down":
+ interface_instance.interface.enabled = False
+ else:
+ self.poutput(self.colorize('Error: ', 'red') + \
+ self.colorize(self.colorize('Invalid admin state parameter for ont ani', 'blue'),
+ 'bold'))
+ return
+ if opts.link_up_down_trap_enable:
+ types = ["trap_disabled", "trap_enabled"]
+ try:
+ assert opts.link_up_down_trap_enable in types, \
+ 'Invalid Enum value for Ont Ani link up down trap enable type \'{}\''\
+ .format(opts.link_up_down_trap_enable)
+ interface_instance.interface.link_up_down_trap_enable = \
+ ietf_interfaces_pb2._INTERFACE_LINKUPDOWNTRAPENABLETYPE.values_by_name[opts.link_up_down_trap_enable.upper()].number
+ except AssertionError, e:
+ self.poutput(self.colorize('Error: ', 'red') + \
+ self.colorize(self.colorize(e.message, 'blue'),
+ 'bold'))
+ return
+
+ if opts.upstream_fec_indicator:
+ if opts.upstream_fec_indicator == 'true':
+ interface_instance.data.upstream_fec_indicator = True
+ elif opts.upstream_fec_indicator == 'false':
+ interface_instance.data.upstream_fec_indicator = False
+ else:
+ m = 'Invalid boolean value for Ont Ani upstream_fec_indicator \'{}\''\
+ .format(opts.upstream_fec_indicator)
+ self.poutput(self.colorize('Error: ', 'red') + \
+ self.colorize(self.colorize(m, 'blue'),
+ 'bold'))
+ return
+ if opts.mgnt_gemport_aes_indicator:
+ if opts.mgnt_gemport_aes_indicator == 'true':
+ interface_instance.data.mgnt_gemport_aes_indicator = True
+ elif opts.mgnt_gemport_aes_indicator == 'false':
+ interface_instance.data.mgnt_gemport_aes_indicator = False
+ else:
+ m = 'Invalid boolean value for Ont Ani mgnt_gemport_aes_indicator \'{}\''\
+ .format(opts.mgnt_gemport_aes_indicator)
+ self.poutput(self.colorize('Error: ', 'red') + \
+ self.colorize(self.colorize(m, 'blue'),
+ 'bold'))
+ return
+
+ if line.strip() == "create":
+ stub.CreateOntani(interface_instance)
+ elif line.strip() == "update":
+ stub.UpdateOntani(interface_instance)
+ elif line.strip() == "delete":
+ stub.DeleteOntani(interface_instance)
+ return
+
+ def help_v_enet(self):
+ self.poutput(
+'''
+v_enet [get | create | update | delete] [-n <name>] [-d <description>] [-a <admin state>]
+ [-l <link up down trap enable type>] [-r <ont ani reference>]
+
+get: displays existing venets
+ Required flags: None
+create: creates venet with the parameters specified with -n, -d, -a, -l, and -r.
+ Required flags: <name>
+update: updates existing venet specified with parameter -n by changing its parameter values
+ specified with -d, -a, -l, -r.
+ Required flags: <name>
+delete: deletes venet specified with parameter -n.
+ Required flags: <name>
+
+-n: <string> name of venet.
+-d: <string> description of venet.
+-a: <string> admin state of venet.
+-l: <enum> link up down trap enable type.
+-r: <string> ont ani reference of this venet.
+
+Example:
+
+v_enet create -n venet-1 -a up -r ontani-1-1-1
+'''
+ )
+
+ @options([
+ make_option('-n', '--name', action="store", dest='name', type='string',
+ help='name of venet', default=None),
+ make_option('-d', '--description', action="store", dest='description',
+ type='string', help='description of venet', default=None),
+ make_option('-a', '--admin_state', action="store", dest='enabled', type='string',
+ help='admin state of venet', default=None),
+ make_option('-l', '--trap', action="store", dest='link_up_down_trap_enable',
+ type='string', help='link up down trap enable type', default=None),
+ make_option('-r', '--ont_ref', action='store', dest='v_ontani_ref',
+ type='string', help='ont ani reference', default=None),
+ ])
+
+ def do_v_enet(self, line, opts):
+ """v_enet get, create -flags <attributes>, update -flags <attributes>, delete -n <name>"""
+ # Ensure that a valid sub-command was provided
+ if line.strip() not in {"get", "create", "update", "delete"}:
+ self.poutput(self.colorize('Error: ', 'red') + \
+ self.colorize(self.colorize(line.strip(), 'blue'),
+ 'bold') + ' is not recognized')
+ return
+
+ stub = voltha_pb2.VolthaLocalServiceStub(self.get_channel())
+
+ if line.strip() == "get":
+ if self.device_id:
+ cg, cpart, cp, ct, vont, ont, venet = self.get_interface_based_on_device()
+ print_pb_list_as_table("VEnet for device ID = {}:".format(self.device_id),
+ venet, {}, self.poutput)
+ else:
+ interface = stub.GetAllVEnetConfig(Empty())
+ print_pb_list_as_table("VEnets:",
+ interface.v_enet_config,
+ {}, self.poutput)
+ return
+
+ interface_instance = VEnetConfig(name = opts.name)
+ interface_instance.interface.name = opts.name
+ if opts.description:
+ interface_instance.interface.description = opts.description
+ interface_instance.interface.type = "v-enet"
+ if opts.enabled:
+ if opts.enabled == "up":
+ interface_instance.interface.enabled = True
+ elif opts.enabled == "down":
+ interface_instance.interface.enabled = False
+ else:
+ self.poutput(self.colorize('Error: ', 'red') + \
+ self.colorize(self.colorize('Invalid admin state parameter for venet', 'blue'),
+ 'bold'))
+ return
+ if opts.link_up_down_trap_enable:
+ types = ["trap_disabled", "trap_enabled"]
+ try:
+ assert opts.link_up_down_trap_enable in types, \
+ 'Invalid Enum value for Venet link up down trap enable type \'{}\''\
+ .format(opts.link_up_down_trap_enable)
+ interface_instance.interface.link_up_down_trap_enable = \
+ ietf_interfaces_pb2._INTERFACE_LINKUPDOWNTRAPENABLETYPE.values_by_name[opts.link_up_down_trap_enable.upper()].number
+ except AssertionError, e:
+ self.poutput(self.colorize('Error: ', 'red') + \
+ self.colorize(self.colorize(e.message, 'blue'),
+ 'bold'))
+ return
+
+ if opts.v_ontani_ref:
+ interface_instance.data.v_ontani_ref = opts.v_ontani_ref
+
+ if line.strip() == "create":
+ stub.CreateVEnet(interface_instance)
+ elif line.strip() == "update":
+ stub.UpdateVEnet(interface_instance)
+ elif line.strip() == "delete":
+ stub.DeleteVEnet(interface_instance)
+ return
diff --git a/netconf/nc_rpc/base/get.py b/netconf/nc_rpc/base/get.py
index 19535f5..b6fdf1e 100644
--- a/netconf/nc_rpc/base/get.py
+++ b/netconf/nc_rpc/base/get.py
@@ -158,6 +158,27 @@
{'subclass': 'device_groups',
'rpc': 'VolthaLocalService-ListDeviceGroups'
},
+ {'subclass': 'channel_groups',
+ 'rpc': 'VolthaLocalService-GetAllChannelgroupConfig'
+ },
+ {'subclass': 'channel_partitions',
+ 'rpc': 'VolthaLocalService-GetAllChannelpartitionConfig'
+ },
+ {'subclass': 'channel_pairs',
+ 'rpc': 'VolthaLocalService-GetAllChannelpairConfig'
+ },
+ {'subclass': 'channel_terminations',
+ 'rpc': 'VolthaLocalService-GetAllChannelterminationConfig'
+ },
+ {'subclass': 'ont_anis',
+ 'rpc': 'VolthaLocalService-GetAllOntaniConfig'
+ },
+ {'subclass': 'v_ont_anis',
+ 'rpc': 'VolthaLocalService-GetAllVOntaniConfig'
+ },
+ {'subclass': 'v_enets',
+ 'rpc': 'VolthaLocalService-GetAllVEnetConfig'
+ },
],
'VolthaInstances': [
{'subclass': None,
diff --git a/ponsim/grpc_server.py b/ponsim/grpc_server.py
index cea0cc4..7ed70d5 100644
--- a/ponsim/grpc_server.py
+++ b/ponsim/grpc_server.py
@@ -23,6 +23,8 @@
add_PonSimServicer_to_server, PonSimDeviceInfo
from google.protobuf.empty_pb2 import Empty
+from voltha.protos.ponsim_pb2 import XPonSimServicer, add_XPonSimServicer_to_server
+
_ = third_party
log = structlog.get_logger()
@@ -56,19 +58,39 @@
def GetStats(self, request, context):
return self.ponsim.get_stats()
+class XPonHandler(XPonSimServicer):
+
+ def __init__(self, thread_pool, x_pon_sim):
+ self.thread_pool = thread_pool
+ self.x_pon_sim = x_pon_sim
+
+ def CreateInterface(self, request, context):
+ self.x_pon_sim.CreateInterface(request)
+ return Empty()
+
+ def UpdateInterface(self, request, context):
+ self.x_pon_sim.UpdateInterface(request)
+ return Empty()
+
+ def RemoveInterface(self, request, context):
+ self.x_pon_sim.RemoveInterface(request)
+ return Empty()
class GrpcServer(object):
- def __init__(self, port, ponsim):
+ def __init__(self, port, ponsim, x_pon_sim):
self.port = port
self.thread_pool = futures.ThreadPoolExecutor(max_workers=10)
self.server = grpc.server(self.thread_pool)
self.ponsim = ponsim
+ self.x_pon_sim = x_pon_sim
def start(self):
log.debug('starting')
handler = FlowUpdateHandler(self.thread_pool, self.ponsim)
add_PonSimServicer_to_server(handler, self.server)
+ x_pon_handler = XPonHandler(self.thread_pool, self.x_pon_sim)
+ add_XPonSimServicer_to_server(x_pon_handler, self.server)
self.server.add_insecure_port('[::]:%s' % self.port)
self.server.start()
log.info('started')
diff --git a/ponsim/main.py b/ponsim/main.py
index 1b11407..3140afd 100755
--- a/ponsim/main.py
+++ b/ponsim/main.py
@@ -31,6 +31,8 @@
from ponsim import PonSim
from realio import RealIo
+from ponsim import XPonSim
+
defs = dict(
config=os.environ.get('CONFIG', './ponsim.yml'),
grpc_port=int(os.environ.get('GRPC_PORT', 50060)),
@@ -157,6 +159,7 @@
# components
self.io = None
self.ponsim = None
+ self.x_pon_sim = None
self.grpc_server = None
self.alarm_config = dict()
@@ -182,7 +185,9 @@
self.ponsim = PonSim(self.args.onus, self.io.egress, self.alarm_config)
self.io.register_ponsim(self.ponsim)
- self.grpc_server = GrpcServer(self.args.grpc_port, self.ponsim)
+ self.x_pon_sim = XPonSim()
+
+ self.grpc_server = GrpcServer(self.args.grpc_port, self.ponsim, self.x_pon_sim)
yield self.grpc_server.start()
self.log.info('started-internal-services')
diff --git a/ponsim/ponsim.py b/ponsim/ponsim.py
index 3adcd4e..619beb1 100644
--- a/ponsim/ponsim.py
+++ b/ponsim/ponsim.py
@@ -471,3 +471,19 @@
if not isinstance(frame, Packet):
frame = Ether(frame)
self.devices[port].ingress(2, frame)
+
+class XPonSim(object):
+ def __init__(self):
+ self.log = structlog.get_logger()
+
+ def CreateInterface(self, request):
+ self.log.info("create-interface-request", interface_type = request.WhichOneof("interface_type"), data = request)
+ return
+
+ def UpdateInterface(self, request):
+ self.log.info("update-interface-request", interface_type = request.WhichOneof("interface_type"), data = request)
+ return
+
+ def RemoveInterface(self, request):
+ self.log.info("remove-interface-request", interface_type = request.WhichOneof("interface_type"), data = request)
+ return
diff --git a/voltha/adapters/adtran_olt/adtran_olt.py b/voltha/adapters/adtran_olt/adtran_olt.py
index 32d34fd..ae66953 100644
--- a/voltha/adapters/adtran_olt/adtran_olt.py
+++ b/voltha/adapters/adtran_olt/adtran_olt.py
@@ -345,3 +345,15 @@
def unsuppress_alarm(self, filter):
log.info('unsuppress_alarm', filter=filter)
raise NotImplementedError()
+
+ def create_interface(self, device, data):
+ raise NotImplementedError()
+
+ def update_interface(self, device, data):
+ raise NotImplementedError()
+
+ def remove_interface(self, device, data):
+ raise NotImplementedError()
+
+ def receive_onu_detect_state(self, device_id, state):
+ raise NotImplementedError()
diff --git a/voltha/adapters/adtran_olt/pon_port.py b/voltha/adapters/adtran_olt/pon_port.py
index 896b8aa..da1bcc4 100644
--- a/voltha/adapters/adtran_olt/pon_port.py
+++ b/voltha/adapters/adtran_olt/pon_port.py
@@ -469,7 +469,8 @@
adapter.child_device_detected(parent_device_id=olt.device_id,
parent_port_no=self._port_no,
child_device_type=onu.vendor_device,
- proxy_address=proxy)
+ proxy_address=proxy,
+ admin_state=AdminState.ENABLED)
def get_next_onu_id(self):
used_ids = [onu.onu_id for onu in self.onus]
diff --git a/voltha/adapters/asfvolt16_olt/asfvolt16_olt.py b/voltha/adapters/asfvolt16_olt/asfvolt16_olt.py
index 94ce1c3..6ef04ce 100644
--- a/voltha/adapters/asfvolt16_olt/asfvolt16_olt.py
+++ b/voltha/adapters/asfvolt16_olt/asfvolt16_olt.py
@@ -31,6 +31,7 @@
device_handler_class = Asfvolt16Handler,
name='asfvolt16_olt',
vendor='Edgecore',
- version='0.1')
+ version='0.1',
+ device_type='asfvolt16_olt')
# register for adapter messages
self.adapter_agent.register_for_inter_adapter_messages()
diff --git a/voltha/adapters/broadcom_onu/broadcom_onu.py b/voltha/adapters/broadcom_onu/broadcom_onu.py
index f852220..732085c 100644
--- a/voltha/adapters/broadcom_onu/broadcom_onu.py
+++ b/voltha/adapters/broadcom_onu/broadcom_onu.py
@@ -164,6 +164,18 @@
def suppress_alarm(self, filter):
raise NotImplementedError()
+ def create_interface(self, device, data):
+ raise NotImplementedError()
+
+ def update_interface(self, device, data):
+ raise NotImplementedError()
+
+ def remove_interface(self, device, data):
+ raise NotImplementedError()
+
+ def receive_onu_detect_state(self, device_id, state):
+ raise NotImplementedError()
+
def unsuppress_alarm(self, filter):
raise NotImplementedError()
diff --git a/voltha/adapters/dpoe_onu/dpoe_onu.py b/voltha/adapters/dpoe_onu/dpoe_onu.py
index 9fd1a9f..c261490 100644
--- a/voltha/adapters/dpoe_onu/dpoe_onu.py
+++ b/voltha/adapters/dpoe_onu/dpoe_onu.py
@@ -410,6 +410,18 @@
proxy_address=proxy_address, msg=msg)
self.incoming_messages.put(msg)
+ def create_interface(self, device, data):
+ raise NotImplementedError()
+
+ def update_interface(self, device, data):
+ raise NotImplementedError()
+
+ def remove_interface(self, device, data):
+ raise NotImplementedError()
+
+ def receive_onu_detect_state(self, device_id, state):
+ raise NotImplementedError()
+
def suppress_alarm(self, filter):
raise NotImplementedError()
diff --git a/voltha/adapters/iadapter.py b/voltha/adapters/iadapter.py
index a85913b..5b916ed 100644
--- a/voltha/adapters/iadapter.py
+++ b/voltha/adapters/iadapter.py
@@ -34,14 +34,14 @@
@implementer(IAdapterInterface)
class IAdapter(object):
- def __init__(self, adapter_agent, config, device_handler_class, name, vendor, version):
+ def __init__(self, adapter_agent, config, device_handler_class, name, vendor, version, device_type):
log.debug('Initializing adapter: {} {} {}'.format(vendor, name, version))
self.adapter_agent = adapter_agent
self.config = config
self.name = name
self.supported_device_types = [
DeviceType(
- id=name,
+ id=device_type,
adapter=name,
accepts_bulk_flow_update=True
)
@@ -147,17 +147,30 @@
def unsuppress_alarm(self, filter):
raise NotImplementedError()
+ def create_interface(self, device, data):
+ raise NotImplementedError()
+
+ def update_interface(self, device, data):
+ raise NotImplementedError()
+
+ def remove_interface(self, device, data):
+ raise NotImplementedError()
+
+ def receive_onu_detect_state(self, proxy_address, state):
+ raise NotImplementedError()
+
"""
OLT Adapter base class
"""
class OltAdapter(IAdapter):
- def __init__(self, adapter_agent, config, device_handler_class, name, vendor, version):
+ def __init__(self, adapter_agent, config, device_handler_class, name, vendor, version, device_type):
super(OltAdapter, self).__init__(adapter_agent,
config,
device_handler_class,
name,
vendor,
- version)
+ version,
+ device_type)
self.logical_device_id_to_root_device_id = dict()
def reconcile_device(self, device):
@@ -198,13 +211,15 @@
ONU Adapter base class
"""
class OnuAdapter(IAdapter):
- def __init__(self, adapter_agent, config, device_handler_class, name, vendor, version):
+ def __init__(self, adapter_agent, config, device_handler_class, name, vendor, version, device_type):
super(OnuAdapter, self).__init__(adapter_agent,
config,
device_handler_class,
name,
vendor,
- version)
+ version,
+ device_type)
+
def reconcile_device(self, device):
self.devices_handlers[device.id] = self.device_handler_class(self, device.id)
# Reconcile only if state was ENABLED
diff --git a/voltha/adapters/interface.py b/voltha/adapters/interface.py
index 1158a4d..1f2da87 100644
--- a/voltha/adapters/interface.py
+++ b/voltha/adapters/interface.py
@@ -240,6 +240,32 @@
# TODO work in progress
# ...
+ # PON Mgnt APIs #
+ def create_interface(device, data):
+ """
+ API to create various interfaces (only some PON interfaces as of now)
+ in the devices
+ """
+
+ def update_interface(device, data):
+ """
+ API to update various interfaces (only some PON interfaces as of now)
+ in the devices
+ """
+
+ def remove_interface(device, data):
+ """
+ API to delete various interfaces (only some PON interfaces as of now)
+ in the devices
+ """
+
+ def receive_onu_detect_state(proxy_address, state):
+ """
+ Receive onu detect state in ONU adapter
+ :param proxy_address: ONU device address
+ :param state: ONU detect state (bool)
+ :return: None
+ """
class IAdapterAgent(Interface):
"""
@@ -276,6 +302,7 @@
parent_port_no,
child_device_type,
proxy_address,
+ admin_state,
**kw):
# TODO add doc
""""""
@@ -349,3 +376,23 @@
:param alarm_event_msg: A protobuf message of AlarmEvent type.
:return: None
"""
+
+ def register_for_onu_detect_state(proxy_address):
+ """
+
+ :return: None
+ """
+
+ def unregister_for_onu_detect_state(proxy_address):
+ """
+
+ :return: None
+ """
+
+ def forward_onu_detect_state(proxy_address, state):
+ """
+ Forward onu detect state to ONU adapter
+ :param proxy_address: ONU device address
+ :param state: ONU detect state (bool)
+ :return: None
+ """
diff --git a/voltha/adapters/maple_olt/maple_olt.py b/voltha/adapters/maple_olt/maple_olt.py
index a690985..528ae01 100644
--- a/voltha/adapters/maple_olt/maple_olt.py
+++ b/voltha/adapters/maple_olt/maple_olt.py
@@ -494,13 +494,24 @@
def receive_inter_adapter_message(self, msg):
pass
+ def create_interface(self, device, data):
+ raise NotImplementedError()
+
+ def update_interface(self, device, data):
+ raise NotImplementedError()
+
+ def remove_interface(self, device, data):
+ raise NotImplementedError()
+
+ def receive_onu_detect_state(self, device_id, state):
+ raise NotImplementedError()
+
def suppress_alarm(self, filter):
raise NotImplementedError()
def unsuppress_alarm(self, filter):
raise NotImplementedError()
-
class MaplePBClientFactory(pb.PBClientFactory, ReconnectingClientFactory):
channel = None
maxDelay = 60
@@ -968,6 +979,7 @@
onu_id=onu_id,
onu_session_id=tunnel_tag # tunnel_tag/gem_port, alloc_id
),
+ admin_state=AdminState.ENABLED,
vlan=tunnel_tag,
serial_number=_data['_vendor_specific']
)
diff --git a/voltha/adapters/microsemi_olt/DeviceManager.py b/voltha/adapters/microsemi_olt/DeviceManager.py
index 24c3e7a..af3058b 100644
--- a/voltha/adapters/microsemi_olt/DeviceManager.py
+++ b/voltha/adapters/microsemi_olt/DeviceManager.py
@@ -135,6 +135,7 @@
onu_id=onu_id,
onu_session_id=onu_session_id
),
+ admin_state=AdminState.ENABLED,
vlan=0
)
diff --git a/voltha/adapters/microsemi_olt/microsemi_olt.py b/voltha/adapters/microsemi_olt/microsemi_olt.py
index b50bbeb..64c6d9a 100644
--- a/voltha/adapters/microsemi_olt/microsemi_olt.py
+++ b/voltha/adapters/microsemi_olt/microsemi_olt.py
@@ -142,6 +142,18 @@
log.debug('bulk-flow-update', device_id=device.id,
flows=flows, groups=groups)
+ def create_interface(self, device, data):
+ raise NotImplementedError()
+
+ def update_interface(self, device, data):
+ raise NotImplementedError()
+
+ def remove_interface(self, device, data):
+ raise NotImplementedError()
+
+ def receive_onu_detect_state(self, device_id, state):
+ raise NotImplementedError()
+
def send_proxied_message(self, proxy_address, msg):
device = self.adaptor_agent.get_device(proxy_address.device_id)
_, _, comm = self.olts[device.mac_address]
diff --git a/voltha/adapters/pmcs_onu/pmcs_onu.py b/voltha/adapters/pmcs_onu/pmcs_onu.py
index fb27220..2da0e10 100644
--- a/voltha/adapters/pmcs_onu/pmcs_onu.py
+++ b/voltha/adapters/pmcs_onu/pmcs_onu.py
@@ -154,6 +154,18 @@
log.info('packet-out', logical_device_id=logical_device_id,
egress_port_no=egress_port_no, msg_len=len(msg))
+ def create_interface(self, device, data):
+ raise NotImplementedError()
+
+ def update_interface(self, device, data):
+ raise NotImplementedError()
+
+ def remove_interface(self, device, data):
+ raise NotImplementedError()
+
+ def receive_onu_detect_state(self, device_id, state):
+ raise NotImplementedError()
+
def receive_inter_adapter_message(self, msg):
raise NotImplementedError()
diff --git a/voltha/adapters/ponsim_olt/ponsim_olt.py b/voltha/adapters/ponsim_olt/ponsim_olt.py
index 6111eb1..4c40cf7 100644
--- a/voltha/adapters/ponsim_olt/ponsim_olt.py
+++ b/voltha/adapters/ponsim_olt/ponsim_olt.py
@@ -48,6 +48,12 @@
from voltha.protos.ponsim_pb2 import FlowTable
from voltha.registry import registry
+from voltha.protos.bbf_fiber_base_pb2 import \
+ ChannelgroupConfig, ChannelpartitionConfig, ChannelpairConfig, ChannelterminationConfig, \
+ OntaniConfig, VOntaniConfig, VEnetConfig
+
+from voltha.protos.ponsim_pb2 import InterfaceConfig
+
_ = third_party
log = structlog.get_logger()
@@ -181,7 +187,8 @@
device_handler_class=PonSimOltHandler,
name='ponsim_olt',
vendor='Voltha project',
- version='0.4')
+ version='0.4',
+ device_type='ponsim_olt')
def update_pm_config(self, device, pm_config):
log.info("adapter-update-pm-config", device=device,
@@ -189,6 +196,18 @@
handler = self.devices_handlers[device.id]
handler.update_pm_config(device, pm_config)
+ def create_interface(self, device, data):
+ log.info('create-interface', device_id=device.id)
+ self.devices_handlers[device.id].create_interface(data)
+
+ def update_interface(self, device, data):
+ log.info('update-interface', device_id=device.id)
+ self.devices_handlers[device.id].update_interface(data)
+
+ def remove_interface(self, device, data):
+ log.info('remove-interface', device_id=device.id)
+ self.devices_handlers[device.id].remove_interface(data)
+
class PonSimOltHandler(object):
def __init__(self, adapter, device_id):
self.adapter = adapter
@@ -322,11 +341,12 @@
self.adapter_agent.child_device_detected(
parent_device_id=device.id,
parent_port_no=1,
- child_device_type='ponsim_onu',
+ child_device_type='PSMO', #''ponsim_onu', # refers notes from ponsim_onu
proxy_address=Device.ProxyAddress(
device_id=device.id,
channel_id=vlan_id
),
+ admin_state=AdminState.ENABLED,
vlan=vlan_id
)
@@ -667,3 +687,47 @@
log.exception('failed-to-submit-kpis', e=e)
self.pm_metrics.start_collector(_collect)
+
+ def get_interface_config(self, data):
+ interfaceConfig = InterfaceConfig()
+ if isinstance(data, ChannelgroupConfig):
+ interfaceConfig.channel_group_config.CopyFrom(data)
+ elif isinstance(data, ChannelpartitionConfig):
+ interfaceConfig.channel_partition_config.CopyFrom(data)
+ elif isinstance(data, ChannelpairConfig):
+ interfaceConfig.channel_pair_config.CopyFrom(data)
+ elif isinstance(data, ChannelterminationConfig):
+ interfaceConfig.channel_termination_config.CopyFrom(data)
+ elif isinstance(data, OntaniConfig):
+ interfaceConfig.ont_ani_config.CopyFrom(data)
+ elif isinstance(data, VOntaniConfig):
+ interfaceConfig.vont_ani_config.CopyFrom(data)
+ elif isinstance(data, VEnetConfig):
+ interfaceConfig.venet_config.CopyFrom(data)
+ else:
+ return None
+ return interfaceConfig
+
+ def create_interface(self, data):
+ interfaceConfig = self.get_interface_config(data)
+ if interfaceConfig is not None:
+ self.log.info('forwarding-create-interface-request-to-olt-for-interface-type', interface_type=type(data))
+ stub = ponsim_pb2.XPonSimStub(self.get_channel())
+ stub.CreateInterface(interfaceConfig)
+ self.log.info('success')
+
+ def update_interface(self, data):
+ interfaceConfig = self.get_interface_config(data)
+ if interfaceConfig is not None:
+ self.log.info('forwarding-update-interface-request-to-olt-for-interface-type', interface_type=type(data))
+ stub = ponsim_pb2.XPonSimStub(self.get_channel())
+ stub.UpdateInterface(interfaceConfig)
+ self.log.info('success')
+
+ def remove_interface(self, data):
+ interfaceConfig = self.get_interface_config(data)
+ if interfaceConfig is not None:
+ self.log.info('forwarding-remove-interface-request-to-olt-for-interface-type', interface_type=type(data))
+ stub = ponsim_pb2.XPonSimStub(self.get_channel())
+ stub.RemoveInterface(interfaceConfig)
+ self.log.info('success')
diff --git a/voltha/adapters/ponsim_onu/ponsim_onu.py b/voltha/adapters/ponsim_onu/ponsim_onu.py
index f34d6ed..04ae976 100644
--- a/voltha/adapters/ponsim_onu/ponsim_onu.py
+++ b/voltha/adapters/ponsim_onu/ponsim_onu.py
@@ -39,12 +39,15 @@
class PonSimOnuAdapter(OnuAdapter):
def __init__(self, adapter_agent, config):
+ #DeviceType of ONU should be same as VENDOR ID of ONU Serial Number as specified by standard
+ #requires for identifying correct adapter or ranged ONU
super(PonSimOnuAdapter, self).__init__(adapter_agent=adapter_agent,
config=config,
device_handler_class = PonSimOnuHandler,
name='ponsim_onu',
vendor='Voltha project',
- version='0.4')
+ version='0.4',
+ device_type='PSMO')
class PonSimOnuHandler(object):
def __init__(self, adapter, device_id):
diff --git a/voltha/adapters/simulated_olt/simulated_olt.py b/voltha/adapters/simulated_olt/simulated_olt.py
index e3860b0..ce3242e 100644
--- a/voltha/adapters/simulated_olt/simulated_olt.py
+++ b/voltha/adapters/simulated_olt/simulated_olt.py
@@ -815,6 +815,18 @@
alarm_lc = LoopingCall(_generate_alarm, device_id)
alarm_lc.start(30)
+ def create_interface(self, device, data):
+ raise NotImplementedError()
+
+ def update_interface(self, device, data):
+ raise NotImplementedError()
+
+ def remove_interface(self, device, data):
+ raise NotImplementedError()
+
+ def receive_onu_detect_state(self, device_id, state):
+ raise NotImplementedError()
+
# ~~~~~~~~~~~~~~~~~~~~ Embedded test Klein rest server ~~~~~~~~~~~~~~~~~~~~
def get_test_control_site(self):
diff --git a/voltha/adapters/simulated_onu/simulated_onu.py b/voltha/adapters/simulated_onu/simulated_onu.py
index 9fc9288..7a27e45 100644
--- a/voltha/adapters/simulated_onu/simulated_onu.py
+++ b/voltha/adapters/simulated_onu/simulated_onu.py
@@ -387,6 +387,18 @@
# just place incoming message to a list
self.incoming_messages.put((proxy_address, msg))
+ def create_interface(self, device, data):
+ raise NotImplementedError()
+
+ def update_interface(self, device, data):
+ raise NotImplementedError()
+
+ def remove_interface(self, device, data):
+ raise NotImplementedError()
+
+ def receive_onu_detect_state(self, device_id, state):
+ raise NotImplementedError()
+
def suppress_alarm(self, filter):
raise NotImplementedError()
diff --git a/voltha/adapters/tibit_olt/tibit_olt.py b/voltha/adapters/tibit_olt/tibit_olt.py
index 4bf40c9..91ff213 100644
--- a/voltha/adapters/tibit_olt/tibit_olt.py
+++ b/voltha/adapters/tibit_olt/tibit_olt.py
@@ -454,6 +454,7 @@
device_id=device.id,
channel_id=vlan_id
),
+ admin_state=AdminState.ENABLED,
vlan=vlan_id
)
@@ -1382,3 +1383,15 @@
# Get and process the Set Response
rc = []
yield self._handle_set_resp(olt_mac, action, rc)
+
+ def create_interface(self, device, data):
+ raise NotImplementedError()
+
+ def update_interface(self, device, data):
+ raise NotImplementedError()
+
+ def remove_interface(self, device, data):
+ raise NotImplementedError()
+
+ def receive_onu_detect_state(self, device_id, state):
+ raise NotImplementedError()
diff --git a/voltha/adapters/tibit_onu/tibit_onu.py b/voltha/adapters/tibit_onu/tibit_onu.py
index 7ee421f..bc18dc7 100644
--- a/voltha/adapters/tibit_onu/tibit_onu.py
+++ b/voltha/adapters/tibit_onu/tibit_onu.py
@@ -537,6 +537,18 @@
proxy_address=proxy_address, msg=msg.show(dump=True))
self.incoming_messages.put(msg)
+ def create_interface(self, device, data):
+ raise NotImplementedError()
+
+ def update_interface(self, device, data):
+ raise NotImplementedError()
+
+ def remove_interface(self, device, data):
+ raise NotImplementedError()
+
+ def receive_onu_detect_state(self, device_id, state):
+ raise NotImplementedError()
+
@inlineCallbacks
def _message_exchange(self, device):
diff --git a/voltha/core/adapter_agent.py b/voltha/core/adapter_agent.py
index 9140cc5..d966c3b 100644
--- a/voltha/core/adapter_agent.py
+++ b/voltha/core/adapter_agent.py
@@ -41,7 +41,6 @@
from voltha.registry import registry
from common.utils.id_generation import create_cluster_device_id
-
@implementer(IAdapterAgent)
class AdapterAgent(object):
"""
@@ -66,6 +65,7 @@
self.event_bus = EventBusClient()
self.packet_out_subscription = None
self.log = structlog.get_logger(adapter_name=adapter_name)
+ self._onu_detect_event_subscriptions = {}
@inlineCallbacks
def start(self):
@@ -194,6 +194,15 @@
# def update_pm_collection(self, device, pm_collection_config):
# return self.adapter.update_pm_collection(device, pm_collection_config)
+ def create_interface (self, device, data):
+ return self.adapter.create_interface (device, data)
+
+ def update_interface (self, device, data):
+ return self.adapter.update_interface (device, data)
+
+ def remove_interface(self, device, data):
+ return self.adapter.remove_interface(device, data)
+
# ~~~~~~~~~~~~~~~~~~~ Adapter-Facing Service ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -211,10 +220,11 @@
:return: Child Device Object or None
"""
# Get all arguments to be used for comparison
- # Note that for now we are only matching on the ONU ID
+ # Note that for now we are only matching on the ONU ID & SERIAL NUMBER
# Other matching fields can be added as required in the future
onu_id = kwargs.pop('onu_id', None)
- if onu_id is None: return None
+ serial_number = kwargs.pop('serial_number', None)
+ if onu_id is None and serial_number is None: return None
# Get all devices
devices = self.root_proxy.get('/devices')
@@ -228,8 +238,22 @@
device = self.get_device(child_id)
# Does this child device match the passed in ONU ID?
- if device.proxy_address.onu_id != onu_id:
- found = False
+ found_onu_id = False
+ if onu_id is not None:
+ if device.proxy_address.onu_id == onu_id:
+ found_onu_id = True
+
+ # Does this child device match the passed in SERIAL NUMBER?
+ found_serial_number = False
+ if serial_number is not None:
+ if device.serial_number == serial_number:
+ found_serial_number = True
+ # Match ONU ID and SERIAL NUMBER
+ if onu_id is not None and serial_number is not None:
+ found = found_onu_id & found_serial_number
+ # Otherwise ONU ID or SERIAL NUMBER
+ else:
+ found = found_onu_id | found_serial_number
# Return the matched child device
if found is True:
@@ -509,17 +533,17 @@
parent_port_no,
child_device_type,
proxy_address,
+ admin_state,
**kw):
# we create new ONU device objects and insert them into the config
- # TODO should we auto-enable the freshly created device? Probably.
device = Device(
id=create_cluster_device_id(self.core.core_store_id),
# id=uuid4().hex[:12],
type=child_device_type,
parent_id=parent_device_id,
parent_port_no=parent_port_no,
- admin_state=AdminState.ENABLED,
proxy_address=proxy_address,
+ admin_state=admin_state,
**kw
)
self._make_up_to_date(
@@ -581,6 +605,13 @@
self._make_up_to_date(
'/devices', device.id, device)
+ def delete_child_device(self, parent_device_id, child_device_id):
+ onu_device = self.root_proxy.get('/devices/{}'.format(child_device_id))
+ if onu_device is not None:
+ if onu_device.parent_id == parent_device_id:
+ self.log.debug('deleting-child-device', parent_device_id=parent_device_id, child_device_id=child_device_id)
+ self._remove_node('/devices', child_device_id)
+
def _gen_rx_proxy_address_topic(self, proxy_address):
"""Generate unique topic name specific to this proxy address for rx"""
topic = 'rx:' + MessageToJson(proxy_address)
@@ -723,3 +754,28 @@
except Exception as e:
self.log.exception('failed-alarm-submission',
type=type(alarm_event_msg))
+
+ # ~~~~~~~~~~~~~~~~~~~ Handle ONU detect ~~~~~~~~~~~~~~~~~~~~~
+
+ def _gen_onu_detect_proxy_address_topic(self, device_id):
+ """Generate unique topic name specific to this device id for onu detect"""
+ topic = str('onu_detect:{}'.format(device_id))
+ return topic
+
+ def register_for_onu_detect_state(self, device_id):
+ topic = self._gen_onu_detect_proxy_address_topic(device_id)
+ self._onu_detect_event_subscriptions[topic] = self.event_bus.subscribe(
+ topic,
+ lambda t, m: self._forward_onu_detect_state(device_id, m))
+
+ def unregister_for_onu_detect_state(self, device_id):
+ topic = self._gen_onu_detect_proxy_address_topic(device_id)
+ self.event_bus.unsubscribe(self._onu_detect_event_subscriptions[topic])
+ del self._onu_detect_event_subscriptions[topic]
+
+ def _forward_onu_detect_state(self, device_id, state):
+ self.adapter.receive_onu_detect_state(device_id, state)
+
+ def forward_onu_detect_state(self, device_id, state):
+ topic = self._gen_onu_detect_proxy_address_topic(device_id)
+ self.event_bus.publish(topic, state)
diff --git a/voltha/core/config/config_rev_persisted.py b/voltha/core/config/config_rev_persisted.py
index 3464664..ad8711f 100644
--- a/voltha/core/config/config_rev_persisted.py
+++ b/voltha/core/config/config_rev_persisted.py
@@ -133,5 +133,5 @@
def tmp_cls_loader(module_name, cls_name):
# TODO this shall be generalized
from voltha.protos import voltha_pb2, health_pb2, adapter_pb2, \
- logical_device_pb2, device_pb2, openflow_13_pb2
+ logical_device_pb2, device_pb2, openflow_13_pb2, bbf_fiber_base_pb2
return getattr(locals()[module_name], cls_name)
diff --git a/voltha/core/core.py b/voltha/core/core.py
index 80bc5c1..7ddb5b8 100644
--- a/voltha/core/core.py
+++ b/voltha/core/core.py
@@ -34,6 +34,10 @@
from voltha.protos.voltha_pb2 import \
Device, LogicalDevice, AlarmFilter
from voltha.registry import IComponent
+from xpon_agent import XponAgent
+from xpon_handler import XponHandler
+from voltha.protos.bbf_fiber_base_pb2 import ChannelgroupConfig, ChannelpartitionConfig, \
+ ChannelpairConfig, OntaniConfig, VOntaniConfig, VEnetConfig
log = structlog.get_logger()
@@ -58,6 +62,7 @@
instance_id=instance_id,
version=version,
log_level=log_level)
+ self.xpon_handler = XponHandler(self)
self.local_handler = LocalHandler(
core=self,
instance_id=instance_id,
@@ -70,6 +75,7 @@
self.alarm_filter_agent = None
self.packet_in_queue = Queue()
self.change_event_queue = Queue()
+ self.xpon_agent = XponAgent(self)
@inlineCallbacks
def start(self, config_backend=None):
@@ -151,6 +157,10 @@
self._handle_add_device(data)
elif isinstance(data, LogicalDevice):
self._handle_add_logical_device(data)
+ elif isinstance(data, (ChannelgroupConfig, ChannelpartitionConfig,
+ ChannelpairConfig, OntaniConfig, VOntaniConfig,
+ VEnetConfig)):
+ self.xpon_agent.create_interface(data)
elif isinstance(data, AlarmFilter):
self._handle_add_alarm_filter(data)
else:
@@ -162,6 +172,10 @@
self._handle_remove_device(data)
elif isinstance(data, LogicalDevice):
self._handle_remove_logical_device(data)
+ elif isinstance(data, (ChannelgroupConfig, ChannelpartitionConfig,
+ ChannelpairConfig, OntaniConfig, VOntaniConfig,
+ VEnetConfig)):
+ self.xpon_agent.remove_interface(data)
elif isinstance(data, AlarmFilter):
self._handle_remove_alarm_filter(data)
else:
@@ -177,6 +191,7 @@
path = '/devices/{}'.format(device.id)
assert device.id not in self.device_agents
self.device_agents[device.id] = yield DeviceAgent(self, device).start()
+ self.xpon_agent.register_interface(device.id, path, update=False)
@inlineCallbacks
def _handle_reconcile_existing_device(self, device, reconcile):
@@ -190,6 +205,8 @@
@inlineCallbacks
def _handle_remove_device(self, device):
if device.id in self.device_agents:
+ path = '/devices/{}'.format(device.id)
+ self.xpon_agent.unregister_interface(device.id, path, update=False)
if self.alarm_filter_agent is not None:
self.alarm_filter_agent.remove_device_filters(device)
diff --git a/voltha/core/device_agent.py b/voltha/core/device_agent.py
index 479ec6f..0de15bc 100644
--- a/voltha/core/device_agent.py
+++ b/voltha/core/device_agent.py
@@ -23,7 +23,7 @@
from twisted.internet.defer import inlineCallbacks, returnValue
from voltha.core.config.config_proxy import CallbackType
-from voltha.protos.common_pb2 import AdminState, OperStatus
+from voltha.protos.common_pb2 import AdminState, OperStatus, ConnectStatus
from voltha.registry import registry
from voltha.protos.openflow_13_pb2 import Flows, FlowGroups
@@ -208,6 +208,9 @@
def update_device(self, device):
self.last_data = device # so that we don't propagate back
self.proxy.update('/', device)
+ if device.oper_status == OperStatus.ACTIVE and device.connect_status == ConnectStatus.REACHABLE:
+ self.log.info('replay-create-interfaces ', device=device.id)
+ self.core.xpon_agent.replay_interface(device.id)
def update_device_pm_config(self, device_pm_config, init=False):
self.callback_data = init# so that we don't push init data
@@ -333,4 +336,3 @@
else:
raise NotImplementedError()
-
diff --git a/voltha/core/global_handler.py b/voltha/core/global_handler.py
index 7c80826..ab02cf0 100644
--- a/voltha/core/global_handler.py
+++ b/voltha/core/global_handler.py
@@ -502,6 +502,316 @@
log.info('grpc-success-response', response=response)
returnValue(response)
+ # bbf_fiber rpcs start
+ @twisted_async
+ def GetAllChannelgroupConfig(self, request, context):
+ log.warning('temp-limited-implementation')
+ # TODO dispatching to local instead of collecting all
+ return self.dispatcher.dispatch(
+ self.instance_id,
+ VolthaLocalServiceStub,
+ 'GetAllChannelgroupConfig',
+ request,
+ context)
+
+ @twisted_async
+ def CreateChannelgroup(self, request, context):
+ log.warning('temp-limited-implementation')
+ # TODO dispatching to local instead of collecting all
+ return self.dispatcher.dispatch(
+ self.instance_id,
+ VolthaLocalServiceStub,
+ 'CreateChannelgroup',
+ request,
+ context)
+
+ @twisted_async
+ def UpdateChannelgroup(self, request, context):
+ log.warning('temp-limited-implementation')
+ # TODO dispatching to local instead of collecting all
+ return self.dispatcher.dispatch(
+ self.instance_id,
+ VolthaLocalServiceStub,
+ 'UpdateChannelgroup',
+ request,
+ context)
+
+ @twisted_async
+ def DeleteChannelgroup(self, request, context):
+ log.warning('temp-limited-implementation')
+ # TODO dispatching to local instead of collecting all
+ return self.dispatcher.dispatch(
+ self.instance_id,
+ VolthaLocalServiceStub,
+ 'DeleteChannelgroup',
+ request,
+ context)
+
+ @twisted_async
+ def GetAllChannelpartitionConfig(self, request, context):
+ log.warning('temp-limited-implementation')
+ # TODO dispatching to local instead of collecting all
+ return self.dispatcher.dispatch(
+ self.instance_id,
+ VolthaLocalServiceStub,
+ 'GetAllChannelpartitionConfig',
+ request,
+ context)
+
+ @twisted_async
+ def CreateChannelpartition(self, request, context):
+ log.warning('temp-limited-implementation')
+ # TODO dispatching to local instead of collecting all
+ return self.dispatcher.dispatch(
+ self.instance_id,
+ VolthaLocalServiceStub,
+ 'CreateChannelpartition',
+ request,
+ context)
+
+ @twisted_async
+ def UpdateChannelpartition(self, request, context):
+ log.warning('temp-limited-implementation')
+ # TODO dispatching to local instead of collecting all
+ return self.dispatcher.dispatch(
+ self.instance_id,
+ VolthaLocalServiceStub,
+ 'UpdateChannelpartition',
+ request,
+ context)
+
+ @twisted_async
+ def DeleteChannelpartition(self, request, context):
+ log.warning('temp-limited-implementation')
+ # TODO dispatching to local instead of collecting all
+ return self.dispatcher.dispatch(
+ self.instance_id,
+ VolthaLocalServiceStub,
+ 'DeleteChannelpartition',
+ request,
+ context)
+
+ @twisted_async
+ def GetAllChannelpairConfig(self, request, context):
+ log.warning('temp-limited-implementation')
+ # TODO dispatching to local instead of collecting all
+ return self.dispatcher.dispatch(
+ self.instance_id,
+ VolthaLocalServiceStub,
+ 'GetAllChannelpairConfig',
+ request,
+ context)
+
+ @twisted_async
+ def CreateChannelpair(self, request, context):
+ log.warning('temp-limited-implementation')
+ # TODO dispatching to local instead of collecting all
+ return self.dispatcher.dispatch(
+ self.instance_id,
+ VolthaLocalServiceStub,
+ 'CreateChannelpair',
+ request,
+ context)
+
+ @twisted_async
+ def UpdateChannelpair(self, request, context):
+ log.warning('temp-limited-implementation')
+ # TODO dispatching to local instead of collecting all
+ return self.dispatcher.dispatch(
+ self.instance_id,
+ VolthaLocalServiceStub,
+ 'UpdateChannelpair',
+ request,
+ context)
+
+ @twisted_async
+ def DeleteChannelpair(self, request, context):
+ log.warning('temp-limited-implementation')
+ # TODO dispatching to local instead of collecting all
+ return self.dispatcher.dispatch(
+ self.instance_id,
+ VolthaLocalServiceStub,
+ 'DeleteChannelpair',
+ request,
+ context)
+
+ @twisted_async
+ def GetAllChannelterminationConfig(self, request, context):
+ log.warning('temp-limited-implementation')
+ # TODO dispatching to local instead of collecting all
+ return self.dispatcher.dispatch(
+ self.instance_id,
+ VolthaLocalServiceStub,
+ 'GetAllChannelterminationConfig',
+ request,
+ context)
+
+ @twisted_async
+ def CreateChanneltermination(self, request, context):
+ log.warning('temp-limited-implementation')
+ # TODO dispatching to local instead of collecting all
+ return self.dispatcher.dispatch(
+ self.instance_id,
+ VolthaLocalServiceStub,
+ 'CreateChanneltermination',
+ request,
+ context)
+
+ @twisted_async
+ def UpdateChanneltermination(self, request, context):
+ log.warning('temp-limited-implementation')
+ # TODO dispatching to local instead of collecting all
+ return self.dispatcher.dispatch(
+ self.instance_id,
+ VolthaLocalServiceStub,
+ 'UpdateChanneltermination',
+ request,
+ context)
+
+ @twisted_async
+ def DeleteChanneltermination(self, request, context):
+ log.warning('temp-limited-implementation')
+ # TODO dispatching to local instead of collecting all
+ return self.dispatcher.dispatch(
+ self.instance_id,
+ VolthaLocalServiceStub,
+ 'DeleteChanneltermination',
+ request,
+ context)
+
+ @twisted_async
+ def GetAllOntaniConfig(self, request, context):
+ log.warning('temp-limited-implementation')
+ # TODO dispatching to local instead of collecting all
+ return self.dispatcher.dispatch(
+ self.instance_id,
+ VolthaLocalServiceStub,
+ 'GetAllOntaniConfig',
+ request,
+ context)
+
+ @twisted_async
+ def CreateOntani(self, request, context):
+ log.warning('temp-limited-implementation')
+ # TODO dispatching to local instead of collecting all
+ return self.dispatcher.dispatch(
+ self.instance_id,
+ VolthaLocalServiceStub,
+ 'CreateOntani',
+ request,
+ context)
+
+ @twisted_async
+ def UpdateOntani(self, request, context):
+ log.warning('temp-limited-implementation')
+ # TODO dispatching to local instead of collecting all
+ return self.dispatcher.dispatch(
+ self.instance_id,
+ VolthaLocalServiceStub,
+ 'UpdateOntani',
+ request,
+ context)
+
+ @twisted_async
+ def DeleteOntani(self, request, context):
+ log.warning('temp-limited-implementation')
+ # TODO dispatching to local instead of collecting all
+ return self.dispatcher.dispatch(
+ self.instance_id,
+ VolthaLocalServiceStub,
+ 'DeleteOntani',
+ request,
+ context)
+
+ @twisted_async
+ def GetAllVOntaniConfig(self, request, context):
+ log.warning('temp-limited-implementation')
+ # TODO dispatching to local instead of collecting all
+ return self.dispatcher.dispatch(
+ self.instance_id,
+ VolthaLocalServiceStub,
+ 'GetAllVOntaniConfig',
+ request,
+ context)
+
+ @twisted_async
+ def CreateVOntani(self, request, context):
+ log.warning('temp-limited-implementation')
+ # TODO dispatching to local instead of collecting all
+ return self.dispatcher.dispatch(
+ self.instance_id,
+ VolthaLocalServiceStub,
+ 'CreateVOntani',
+ request,
+ context)
+
+ @twisted_async
+ def UpdateVOntani(self, request, context):
+ log.warning('temp-limited-implementation')
+ # TODO dispatching to local instead of collecting all
+ return self.dispatcher.dispatch(
+ self.instance_id,
+ VolthaLocalServiceStub,
+ 'UpdateVOntani',
+ request,
+ context)
+
+ @twisted_async
+ def DeleteVOntani(self, request, context):
+ log.warning('temp-limited-implementation')
+ # TODO dispatching to local instead of collecting all
+ return self.dispatcher.dispatch(
+ self.instance_id,
+ VolthaLocalServiceStub,
+ 'DeleteVOntani',
+ request,
+ context)
+
+ @twisted_async
+ def GetAllVEnetConfig(self, request, context):
+ log.warning('temp-limited-implementation')
+ # TODO dispatching to local instead of collecting all
+ return self.dispatcher.dispatch(
+ self.instance_id,
+ VolthaLocalServiceStub,
+ 'GetAllVEnetConfig',
+ request,
+ context)
+
+ @twisted_async
+ def CreateVEnet(self, request, context):
+ log.warning('temp-limited-implementation')
+ # TODO dispatching to local instead of collecting all
+ return self.dispatcher.dispatch(
+ self.instance_id,
+ VolthaLocalServiceStub,
+ 'CreateVEnet',
+ request,
+ context)
+
+ @twisted_async
+ def UpdateVEnet(self, request, context):
+ log.warning('temp-limited-implementation')
+ # TODO dispatching to local instead of collecting all
+ return self.dispatcher.dispatch(
+ self.instance_id,
+ VolthaLocalServiceStub,
+ 'UpdateVEnet',
+ request,
+ context)
+
+ @twisted_async
+ def DeleteVEnet(self, request, context):
+ log.warning('temp-limited-implementation')
+ # TODO dispatching to local instead of collecting all
+ return self.dispatcher.dispatch(
+ self.instance_id,
+ VolthaLocalServiceStub,
+ 'DeleteVEnet',
+ request,
+ context)
+ # bbf_fiber rpcs end
+
@twisted_async
@inlineCallbacks
def CreateAlarmFilter(self, request, context):
diff --git a/voltha/core/local_handler.py b/voltha/core/local_handler.py
index bc36a35..fb02ecc 100644
--- a/voltha/core/local_handler.py
+++ b/voltha/core/local_handler.py
@@ -32,6 +32,7 @@
AlarmFilter, AlarmFilters, SelfTestResponse
from voltha.protos.device_pb2 import PmConfigs, Images
from voltha.registry import registry
+from requests.api import request
log = structlog.get_logger()
@@ -66,6 +67,8 @@
else:
self.root = ConfigRoot(VolthaInstance(**self.init_kw))
+ self.core.xpon_handler.start(self.root)
+
registry('grpc_server').register(
add_VolthaLocalServiceServicer_to_server, self)
log.info('started')
@@ -564,6 +567,120 @@
context.set_code(StatusCode.NOT_FOUND)
return DeviceGroup()
+ # bbf_fiber rpcs start
+ @twisted_async
+ def GetAllChannelgroupConfig(self, request, context):
+ return self.core.xpon_handler.get_all_channel_group_config(request, context)
+
+ @twisted_async
+ def CreateChannelgroup(self, request, context):
+ return self.core.xpon_handler.create_channel_group(request, context)
+
+ @twisted_async
+ def UpdateChannelgroup(self, request, context):
+ return self.core.xpon_handler.update_channel_group(request, context)
+
+ @twisted_async
+ def DeleteChannelgroup(self, request, context):
+ return self.core.xpon_handler.delete_channel_group(request, context)
+
+ @twisted_async
+ def GetAllChannelpartitionConfig(self, request, context):
+ return self.core.xpon_handler.get_all_channel_partition_config(request, context)
+
+ @twisted_async
+ def CreateChannelpartition(self, request, context):
+ return self.core.xpon_handler.create_channel_partition(request, context)
+
+ @twisted_async
+ def UpdateChannelpartition(self, request, context):
+ return self.core.xpon_handler.update_channel_partition(request, context)
+
+ @twisted_async
+ def DeleteChannelpartition(self, request, context):
+ return self.core.xpon_handler.delete_channel_partition(request, context)
+
+ @twisted_async
+ def GetAllChannelpairConfig(self, request, context):
+ return self.core.xpon_handler.get_all_channel_pair_config(request, context)
+
+ @twisted_async
+ def CreateChannelpair(self, request, context):
+ return self.core.xpon_handler.create_channel_pair(request, context)
+
+ @twisted_async
+ def UpdateChannelpair(self, request, context):
+ return self.core.xpon_handler.update_channel_pair(request, context)
+
+ @twisted_async
+ def DeleteChannelpair(self, request, context):
+ return self.core.xpon_handler.delete_channel_pair(request, context)
+
+ @twisted_async
+ def GetAllChannelterminationConfig(self, request, context):
+ return self.core.xpon_handler.get_all_channel_termination_config(request, context)
+
+ @twisted_async
+ def CreateChanneltermination(self, request, context):
+ return self.core.xpon_handler.create_channel_termination(request, context)
+
+ @twisted_async
+ def UpdateChanneltermination(self, request, context):
+ return self.core.xpon_handler.update_channel_termination(request, context)
+
+ @twisted_async
+ def DeleteChanneltermination(self, request, context):
+ return self.core.xpon_handler.delete_channel_termination(request, context)
+
+ @twisted_async
+ def GetAllOntaniConfig(self, request, context):
+ return self.core.xpon_handler.get_all_ont_ani_config(request, context)
+
+ @twisted_async
+ def CreateOntani(self, request, context):
+ return self.core.xpon_handler.create_ont_ani(request, context)
+
+ @twisted_async
+ def UpdateOntani(self, request, context):
+ return self.core.xpon_handler.update_ont_ani(request, context)
+
+ @twisted_async
+ def DeleteOntani(self, request, context):
+ return self.core.xpon_handler.delete_ont_ani(request, context)
+
+ @twisted_async
+ def GetAllVOntaniConfig(self, request, context):
+ return self.core.xpon_handler.get_all_v_ont_ani_config(request, context)
+
+ @twisted_async
+ def CreateVOntani(self, request, context):
+ return self.core.xpon_handler.create_v_ont_ani(request, context)
+
+ @twisted_async
+ def UpdateVOntani(self, request, context):
+ return self.core.xpon_handler.update_v_ont_ani(request, context)
+
+ @twisted_async
+ def DeleteVOntani(self, request, context):
+ return self.core.xpon_handler.delete_v_ont_ani(request, context)
+
+ @twisted_async
+ def GetAllVEnetConfig(self, request, context):
+ return self.core.xpon_handler.get_all_v_enet_config(request, context)
+
+ @twisted_async
+ def CreateVEnet(self, request, context):
+ return self.core.xpon_handler.create_v_enet(request, context)
+
+ @twisted_async
+ def UpdateVEnet(self, request, context):
+ return self.core.xpon_handler.update_v_enet(request, context)
+
+ @twisted_async
+ def DeleteVEnet(self, request, context):
+ return self.core.xpon_handler.delete_v_enet(request, context)
+ # bbf_fiber rpcs end
+
def StreamPacketsOut(self, request_iterator, context):
@twisted_async
diff --git a/voltha/core/xpon_agent.py b/voltha/core/xpon_agent.py
new file mode 100644
index 0000000..489ff90
--- /dev/null
+++ b/voltha/core/xpon_agent.py
@@ -0,0 +1,371 @@
+# Copyright 2017 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 sys
+import functools
+
+from voltha.registry import registry
+from voltha.core.config.config_proxy import CallbackType
+from voltha.protos.bbf_fiber_base_pb2 import ChannelgroupConfig, ChannelpartitionConfig, \
+ ChannelpairConfig, ChannelterminationConfig, OntaniConfig, VOntaniConfig, VEnetConfig
+from voltha.protos.device_pb2 import Device
+from voltha.protos.common_pb2 import AdminState
+
+log = structlog.get_logger()
+
+class XponAgent(object):
+
+ interfaces = {ChannelgroupConfig: {'path': '/channel_groups/{}', 'path_keys': ['name'], 'device_id' : ''},
+ ChannelpartitionConfig: {'path': '/channel_partitions/{}', 'path_keys': ['name'], 'device_id' : ''},
+ ChannelpairConfig: {'path': '/channel_pairs/{}', 'path_keys': ['name'], 'device_id' : ''},
+ ChannelterminationConfig: {'path': '/devices/{}/channel_terminations/{}', 'path_keys': ['id', 'name'], 'device_id' : 'id'},
+ OntaniConfig: {'path': '/ont_anis/{}', 'path_keys': ['name'], 'device_id' : ''},
+ VOntaniConfig: {'path': '/v_ont_anis/{}', 'path_keys': ['name'], 'device_id' : ''},
+ VEnetConfig: {'path': '/v_enets/{}', 'path_keys': ['name'], 'device_id' : ''}
+ }
+
+ interface_stack = {ChannelgroupConfig: {'parent': None, 'parent_path' : None, 'parent_path_keys': [None]},
+ ChannelpartitionConfig: {'parent': ChannelgroupConfig, 'parent_path' : '/channel_groups/{}', 'parent_path_keys': ['data.channelgroup_ref']},
+ ChannelpairConfig: {'parent': ChannelpartitionConfig, 'parent_path': '/channel_partitions/{}', 'parent_path_keys': ['data.channelpartition_ref']},
+ ChannelterminationConfig: {'parent': ChannelpairConfig, 'parent_path': '/channel_pairs/{}', 'parent_path_keys': ['data.channelpair_ref']},
+ #VOntaniConfig: {'parent': ChannelpartitionConfig, 'parent_path': '/channel_partitions/{}', 'parent_path_keys': ['data.channelpartition_ref']},
+ VOntaniConfig: {'parent': ChannelpairConfig, 'parent_path': '/channel_pairs/{}', 'parent_path_keys': ['data.preferred_chanpair']},
+ OntaniConfig: {'parent': VOntaniConfig, 'parent_path': '/v_ont_anis/{}', 'parent_path_keys': ['name']},
+ VEnetConfig: {'parent': VOntaniConfig, 'parent_path': '/v_ont_anis/{}', 'parent_path_keys': ['data.v_ontani_ref']}
+ }
+
+ def __init__(self, core):
+ self.core = core
+ self.preData = None
+ self.inReplay = False
+ return
+
+ def get_device_adapter_agent(self, device_id):
+ device = self.core.get_proxy('/devices/{}'.format(device_id)).get()
+ assert device.adapter != ''
+ adapter_agent = registry('adapter_loader').get_agent(device.adapter)
+ log.debug('get-device-adapter-agent', device=device, adapter_agent=adapter_agent)
+ return device, adapter_agent
+
+ def get_interface_path(self, data):
+ val = self.interfaces[type(data)]
+ id_val = {}
+ count = 0
+ for key in val['path_keys']:
+ id_val[count] = getattr(data, key)
+ count+=1
+ path = val['path'].format(*id_val.values())
+ return path
+
+ def get_device_id(self, data):
+ val = self.interfaces[type(data)]
+ device_id = None if val['device_id'] is '' else getattr(data, val['device_id'])
+ if device_id is None:
+ if(isinstance(data, ChannelpairConfig)):
+ device_items = self.core.get_proxy('/').get('/devices')
+ for device_item in device_items:
+ items = self.core.get_proxy('/').get(
+ '/devices/{}/channel_terminations'.format(device_item.id))
+ for item in items:
+ if item.data.channelpair_ref == data.name:
+ return self.get_device_id(item)
+ return None
+ elif(isinstance(data, ChannelpartitionConfig)):
+ items = self.core.get_proxy('/').get('/channel_pairs')
+ for item in items:
+ if item.data.channelpartition_ref == data.name:
+ return self.get_device_id(item)
+ return None
+ elif(isinstance(data, ChannelgroupConfig)):
+ items = self.core.get_proxy('/').get('/channel_partitions')
+ for item in items:
+ if item.data.channelgroup_ref == data.name:
+ return self.get_device_id(item)
+ return None
+ # Take care of ont ani and v ont ani
+ elif(isinstance(data, VOntaniConfig)):
+ channel_part_items = self.core.get_proxy('/').get('/channel_partitions')
+ channel_pair_items = self.core.get_proxy('/').get('/channel_pairs')
+ for channel_part_item in channel_part_items:
+ if channel_part_item.name == data.data.parent_ref:
+ return self.get_device_id(channel_part_item)
+ for channel_pair_item in channel_pair_items:
+ if channel_pair_item.name == data.data.preferred_chanpair or \
+ channel_pair_item.name == data.data.protection_chanpair:
+ return self.get_device_id(channel_pair_item)
+ return None
+ elif(isinstance(data, OntaniConfig)):
+ v_ont_ani_items = self.core.get_proxy('/').get('/v_ont_anis')
+ for v_ont_ani_item in v_ont_ani_items:
+ if v_ont_ani_item.name == data.name:
+ return self.get_device_id(v_ont_ani_item)
+ return None
+ elif(isinstance(data, VEnetConfig)):
+ v_ont_ani_items = self.core.get_proxy('/').get('/v_ont_anis')
+ for v_ont_ani_item in v_ont_ani_items:
+ if v_ont_ani_item.name == data.data.v_ontani_ref:
+ return self.get_device_id(v_ont_ani_item)
+ return None
+ return device_id
+
+ def get_parent_data(self, data):
+ if data is None:
+ return None
+ val = self.interface_stack[type(data)]
+ if val['parent'] is None:
+ return None
+ id_val = {}
+ count = 0
+ for key in val['parent_path_keys']:
+ id_val[count] = self.rgetattr(data, key)
+ count+=1
+ parent_path = val['parent_path'].format(*id_val.values())
+ try:
+ parent_data = self.core.get_proxy('/').get(parent_path)
+ return parent_data
+ except ValueError:
+ log.info('xpon-agent-warning-interface-cannot-get-parent', data=data)
+ return None
+
+ def rgetattr(self, obj, attr):
+ def _getattr(obj, name):
+ return getattr(obj, name)
+ return functools.reduce(_getattr, [obj]+attr.split('.'))
+
+ def is_valid_interface(self, data):
+ valid = False
+ for key in self.interfaces.keys():
+ valid |= isinstance(data, key)
+ return valid
+
+ def register_interface(self, device_id, path, update=True):
+ log.info('register-interface:', device_id=device_id, path=path)
+ try:
+ interface_proxy = self.core.get_proxy(path)
+ if update:
+ interface_proxy.register_callback(CallbackType.POST_UPDATE, self.update_interface, device_id)
+ else:
+ interface_proxy.register_callback(CallbackType.POST_ADD, self.create_interface, device_id)
+ interface_proxy.register_callback(CallbackType.POST_REMOVE, self.remove_interface, device_id)
+ except:
+ print "Unexpected error:", sys.exc_info()[0]
+
+ def unregister_interface(self, device_id, path, update=True):
+ log.info('unregister-interface:', device_id=device_id, path=path)
+ try:
+ interface_proxy = self.core.get_proxy(path)
+ if update:
+ interface_proxy.unregister_callback(CallbackType.POST_UPDATE, self.update_interface, device_id)
+ else:
+ interface_proxy.unregister_callback(CallbackType.POST_ADD, self.create_interface, device_id)
+ interface_proxy.unregister_callback(CallbackType.POST_REMOVE, self.remove_interface, device_id)
+ except:
+ print "Unexpected error:", sys.exc_info()[0]
+
+ def create_interface(self, data, device_id=None):
+ if device_id is None:
+ device_id = self.get_device_id(data)
+ if not self.is_valid_interface(data):
+ log.info('xpon-agent-create-interface-invalid-interface-type', type=type(data).__name__)
+ return
+ self.register_interface(device_id=device_id, path=self.get_interface_path(data))
+ if device_id is not None:
+ if(isinstance(data, ChannelterminationConfig)):
+ self.create_channel_termination(data, device_id)
+ elif(isinstance(data, VOntaniConfig)):
+ self.create_v_ont_ani(data, device_id)
+ else:
+ log.info('xpon-agent-create-interface:', device_id=device_id, data=data)
+ device, adapter_agent = self.get_device_adapter_agent(device_id)
+ adapter_agent.create_interface(device=device, data=data)
+
+ def update_interface(self, data, device_id):
+ if not self.is_valid_interface(data):
+ log.info('xpon-agent-update-interface-invalid-interface-type', type=type(data).__name__)
+ return
+ if device_id is None:
+ device_id = self.get_device_id(data)
+ if device_id is not None:
+ # This can be any interface
+ device, adapter_agent = self.get_device_adapter_agent(device_id)
+ interfaces = []
+ ont_interfaces = []
+ parent_data = self.get_parent_data(data)
+ pre_parent_data = self.get_parent_data(self.preData)
+ if parent_data is not None and pre_parent_data is None:
+ while parent_data is not None:
+ interfaces.insert(0, parent_data)
+ parent_data = self.get_parent_data(parent_data)
+
+ for interface in interfaces:
+ log.info('xpon-agent-creating-interface', device_id=device_id, data=interface)
+ adapter_agent.create_interface(device=device, data=interface)
+
+ venet_items = self.core.get_proxy('/').get('/v_enets')
+ for venet in venet_items:
+ if device_id == self.get_device_id(venet):
+ ont_interfaces.insert(0, venet)
+ parent_data = self.get_parent_data(venet)
+ while not isinstance(parent_data, ChannelpairConfig):
+ ont_interfaces.insert(0, parent_data)
+ parent_data = self.get_parent_data(parent_data)
+
+ for ont_interface in ont_interfaces:
+ log.info('xpon-agent-creating-ont-interface', device_id=device_id, data=ont_interface)
+ adapter_agent.create_interface(device=device, data=ont_interface)
+
+ log.info('xpon-agent-updating-interface', device_id=device_id, data=data)
+ adapter_agent.update_interface(device=device, data=data)
+
+ def remove_interface(self, data, device_id=None):
+ if device_id is None:
+ device_id = self.get_device_id(data)
+ if not self.is_valid_interface(data):
+ log.info('xpon-agent-remove-interface-invalid-interface-type', type=type(data).__name__)
+ return
+ log.info('xpon-agent-remove-interface:', device_id=device_id, data=data)
+ if device_id is not None:
+ if(isinstance(data, ChannelterminationConfig)):
+ self.remove_channel_termination(data, device_id)
+ else:
+ device, adapter_agent = self.get_device_adapter_agent(device_id)
+ adapter_agent.remove_interface(device=device, data=data)
+ if isinstance(data, VOntaniConfig):
+ self.delete_onu_device(device_id=device_id, v_ont_ani=data)
+
+ def create_channel_termination(self, data, device_id):
+ device, adapter_agent = self.get_device_adapter_agent(device_id)
+ channel_pair = self.get_parent_data(data)
+ channel_part = self.get_parent_data(channel_pair)
+ channel_group = self.get_parent_data(channel_part)
+
+ if channel_group:
+ log.info('xpon-agent-creating-channel-group', device_id=device_id, data=channel_group)
+ adapter_agent.create_interface(device=device, data=channel_group)
+ if channel_part:
+ log.info('xpon-agent-creating-channel-partition:', device_id=device_id, data=channel_part)
+ adapter_agent.create_interface(device=device, data=channel_part)
+ if channel_pair:
+ log.info('xpon-agent-creating-channel-pair:', device_id=device_id, data=channel_pair)
+ adapter_agent.create_interface(device=device, data=channel_pair)
+ log.info('xpon-agent-creating-channel-termination:', device_id=device_id, data=data)
+ adapter_agent.create_interface(device=device, data=data)
+ # Take care of ont ani and v ont ani
+ vont_items = self.core.get_proxy('/').get('/v_ont_anis')
+ for vont in vont_items:
+ vont_id = self.get_device_id(vont)
+ if device_id == vont_id:
+ self.create_v_ont_ani(vont, device_id)
+
+ def create_v_ont_ani(self, data, device_id):
+ if not self.inReplay:
+ self.create_onu_device(device_id=device_id, v_ont_ani=data)
+ device, adapter_agent = self.get_device_adapter_agent(device_id)
+ venets = self.core.get_proxy('/').get('/v_enets')
+ log.info('xpon-agent-creating-vont-ani:', device_id=device_id, data=data)
+ adapter_agent.create_interface(device=device, data=data)
+
+ try:
+ ont_ani = self.core.get_proxy('/').get('/ont_anis/{}'.format(data.name))
+ log.info('xpon-agent-create-v-ont-ani-creating-ont-ani:', device_id=device_id, data=ont_ani)
+ adapter_agent.create_interface(device=device, data=ont_ani)
+ except KeyError:
+ log.info('xpon-agent-create-v-ont-ani-there-is-no-ont-ani-to-create')
+
+ for venet in venets:
+ if venet.data.v_ontani_ref == data.name:
+ log.info('xpon-agent-create-v-ont-ani-creating-v-enet:', device_id=device_id, data=venet)
+ adapter_agent.create_interface(device=device, data=venet)
+
+ def remove_channel_termination(self, data, device_id):
+ device, adapter_agent = self.get_device_adapter_agent(device_id)
+ log.info('xpon-agent-removing-channel-termination:', device_id=device_id, data=data)
+ adapter_agent.remove_interface(device=device, data=data)
+
+ if data.data.channelpair_ref:
+ channel_pair = self.get_parent_data(data)
+ log.info('xpon-agent-removing-channel-pair:', device_id=device_id, data=channel_pair)
+ adapter_agent.remove_interface(device=device, data=channel_pair)
+ # Remove vontani and ontani if it has reference to cpair
+ items = self.core.get_proxy('/').get('/v_ont_anis')
+ for item in items:
+ if (item.data.preferred_chanpair == channel_pair.name or \
+ item.data.protection_chanpair == channel_pair.name):
+ log.info('xpon-agent-removing-vont-ani:', device_id=device_id, data=item)
+ adapter_agent.remove_interface(device=device, data=item)
+ self.delete_onu_device(device_id=device_id, v_ont_ani=item)
+
+ venets_items = self.core.get_proxy('/').get('/v_enets')
+ for venet in venets_items:
+ if item.name == venet.data.v_ontani_ref:
+ log.info('xpon-agent-removing-v-enet:', device_id=device_id, data=venet)
+ adapter_agent.remove_interface(device=device, data=venet)
+
+ ontani_items = self.core.get_proxy('/').get('/ont_anis')
+ for ontani_item in ontani_items:
+ if ontani_item.name == item.name:
+ log.info('xpon-agent-removing-ont-ani:', device_id=device_id, data=ontani_item)
+ adapter_agent.remove_interface(device=device, data=ontani_item)
+ # Remove cpart if exists
+ if channel_pair.data.channelpartition_ref:
+ channel_part = self.get_parent_data(channel_pair)
+ log.info('xpon-agent-removing-channel-partition:', device_id=device_id, data=channel_part)
+ adapter_agent.remove_interface(device=device, data=channel_part)
+
+ if channel_part.data.channelgroup_ref:
+ channel_group = self.get_parent_data(channel_part)
+ log.info('xpon-agent-removing-channel-group:', device_id=device_id, data=channel_group)
+ adapter_agent.remove_interface(device=device, data=channel_group)
+
+ def replay_interface(self, device_id):
+ self.inReplay = True
+ ct_items = self.core.get_proxy('/').get('/devices/{}/channel_terminations'.format(device_id))
+ for ct in ct_items:
+ self.create_interface(data=ct, device_id=device_id)
+ self.inReplay = False
+
+ def get_port_num(self, device_id, label):
+ log.info('get-port-num:', label=label, device_id=device_id)
+ ports = self.core.get_proxy('/').get('/devices/{}/ports'.format(device_id))
+ log.info('get-port-num:', label=label, device_id=device_id, ports=ports)
+ for port in ports:
+ if port.label == label:
+ return port.port_no
+ return 0
+
+ def create_onu_device(self, device_id, v_ont_ani):
+ log.info('create-onu-device', v_ont_ani=v_ont_ani, device=device_id)
+ device, adapter_agent = self.get_device_adapter_agent(device_id)
+ parent_chnl_pair_id = self.get_port_num(device.id, v_ont_ani.data.preferred_chanpair)
+ log.info('create-onu-device:', parent_chnl_pair_id=parent_chnl_pair_id)
+ onu_type = v_ont_ani.data.expected_serial_number[:4]
+ proxy_address = Device.ProxyAddress(device_id=device.id, channel_id=parent_chnl_pair_id,
+ onu_id=v_ont_ani.data.onu_id, onu_session_id=v_ont_ani.data.onu_id)
+ adapter_agent.child_device_detected(parent_device_id=device.id, parent_port_no=parent_chnl_pair_id,
+ child_device_type=onu_type,
+ proxy_address=proxy_address,
+ root=True, serial_number=v_ont_ani.data.expected_serial_number,
+ admin_state=AdminState.ENABLED if v_ont_ani.interface.enabled else AdminState.DISABLED
+ )
+ return
+
+ def delete_onu_device(self, device_id, v_ont_ani):
+ log.info('delete-onu-device', v_ont_ani=v_ont_ani, device=device_id)
+ device, adapter_agent = self.get_device_adapter_agent(device_id)
+ onu_device = adapter_agent.get_child_device(parent_device_id=device_id, serial_number=v_ont_ani.data.expected_serial_number)
+ if onu_device is not None:
+ adapter_agent.delete_child_device(device_id, onu_device.id)
+ return
diff --git a/voltha/core/xpon_handler.py b/voltha/core/xpon_handler.py
new file mode 100644
index 0000000..6e461ff
--- /dev/null
+++ b/voltha/core/xpon_handler.py
@@ -0,0 +1,812 @@
+# Copyright 2017 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.
+#
+from Queue import Empty as QueueEmpty
+
+import structlog
+import re
+from uuid import uuid4
+
+from google.protobuf.empty_pb2 import Empty
+from grpc import StatusCode
+
+from voltha.protos.bbf_fiber_base_pb2 import \
+ AllChannelgroupConfig, ChannelgroupConfig, \
+ AllChannelpairConfig, ChannelpairConfig, \
+ AllChannelpartitionConfig, ChannelpartitionConfig, \
+ AllChannelterminationConfig, ChannelterminationConfig, \
+ AllOntaniConfig, OntaniConfig, AllVOntaniConfig , VOntaniConfig, \
+ AllVEnetConfig, VEnetConfig
+
+from voltha.protos.device_pb2 import Device
+from voltha.protos.common_pb2 import AdminState
+
+from requests.api import request
+
+log = structlog.get_logger()
+
+
+class XponHandler(object):
+ def __init__(self, core):
+ self.core = core
+ self.root = None
+
+ def start(self, root):
+ log.debug('starting xpon_handler')
+ self.root = root
+
+ def get_all_channel_group_config(self, request, context):
+ log.info('grpc-request', request=request)
+ items = self.root.get('/channel_groups')
+ return AllChannelgroupConfig(channelgroup_config=items)
+
+ def create_channel_group(self, request, context):
+ log.info('grpc-request', request=request)
+
+ try:
+ assert isinstance(request, ChannelgroupConfig)
+ assert self.validate_interface(request, context)
+ log.debug('creating-channel-group', name=request.name)
+ self.root.add('/channel_groups', request)
+
+ return Empty()
+ except AssertionError, e:
+ return Empty()
+ except ValueError:
+ context.set_details(
+ 'Duplicated channel group \'{}\' cannot be created'.format(request.name))
+ context.set_code(StatusCode.INVALID_ARGUMENT)
+ return Empty()
+
+ def update_channel_group(self, request, context):
+ log.info('grpc-request', request=request)
+
+ if '/' in request.name:
+ context.set_details(
+ 'Malformed name \'{}\''.format(request.name))
+ context.set_code(StatusCode.INVALID_ARGUMENT)
+ return ChannelgroupConfig()
+
+ try:
+ assert isinstance(request, ChannelgroupConfig)
+ assert self.validate_interface(request, context)
+
+ path = '/channel_groups/{}'.format(request.name)
+ log.debug('updating-channel-group', name=request.name)
+ self.root.update(path, request, strict=True)
+ return Empty()
+
+ except AssertionError, e:
+ return Empty()
+
+ except KeyError:
+ context.set_details(
+ 'channel group \'{}\' not found'.format(request.name))
+ context.set_code(StatusCode.NOT_FOUND)
+ return Empty()
+
+ def delete_channel_group(self, request, context):
+ log.info('grpc-request', request=request)
+
+ if '/' in request.name:
+ context.set_details(
+ 'Malformed name \'{}\''.format(request.name))
+ context.set_code(StatusCode.INVALID_ARGUMENT)
+ return Empty()
+
+ try:
+ assert isinstance(request, ChannelgroupConfig)
+ known_channel_group_ref = dict(
+ (dt.data.channelgroup_ref, dt) for dt in self.root.get('/channel_partitions'))
+ known_channel_group_ref_1 = dict(
+ (dt.data.channelgroup_ref, dt) for dt in self.root.get('/channel_pairs'))
+ reference = "channel partition"
+ assert request.name not in known_channel_group_ref
+ reference = "channel pair"
+ assert request.name not in known_channel_group_ref_1
+ path = '/channel_groups/{}'.format(request.name)
+ log.debug('removing-channel-group', name=request.name)
+ self.root.remove(path)
+
+ return Empty()
+
+ except AssertionError:
+ context.set_details(
+ 'The channel group -- \'{}\' is referenced by {}'.format(request.name, reference))
+ context.set_code(StatusCode.INVALID_ARGUMENT)
+ return Empty()
+
+ except KeyError:
+ context.set_details(
+ 'channel group \'{}\' not found'.format(request.name))
+ context.set_code(StatusCode.NOT_FOUND)
+ return Empty()
+
+ def get_all_channel_partition_config(self, request, context):
+ log.info('grpc-request', request=request)
+ items = self.root.get('/channel_partitions')
+ return AllChannelpartitionConfig(channelpartition_config=items)
+
+ def create_channel_partition(self, request, context):
+ log.info('grpc-request', request=request)
+
+ try:
+ assert isinstance(request, ChannelpartitionConfig)
+ assert self.validate_interface(request, context)
+ log.debug('creating-channel-partition', name=request.name)
+ self.root.add('/channel_partitions', request)
+
+ return Empty()
+ except AssertionError, e:
+ return Empty()
+ except ValueError:
+ context.set_details(
+ 'Duplicated channel partition \'{}\' cannot be created'.format(request.name))
+ context.set_code(StatusCode.INVALID_ARGUMENT)
+ return Empty()
+
+ def update_channel_partition(self, request, context):
+ log.info('grpc-request', request=request)
+
+ if '/' in request.name:
+ context.set_details(
+ 'Malformed name \'{}\''.format(request.name))
+ context.set_code(StatusCode.INVALID_ARGUMENT)
+ return ChannelpartitionConfig()
+
+ try:
+ assert isinstance(request, ChannelpartitionConfig)
+ assert self.validate_interface(request, context)
+
+ path = '/channel_partitions/{}'.format(request.name)
+ log.debug('updating-channel-partition', name=request.name)
+ self.root.update(path, request, strict=True)
+ return Empty()
+
+ except AssertionError, e:
+ return Empty()
+
+ except KeyError:
+ context.set_details(
+ 'channel partition \'{}\' not found'.format(request.name))
+ context.set_code(StatusCode.NOT_FOUND)
+ return Empty()
+
+ def delete_channel_partition(self, request, context):
+ log.info('grpc-request', request=request)
+
+ if '/' in request.name:
+ context.set_details(
+ 'Malformed name \'{}\''.format(request.name))
+ context.set_code(StatusCode.INVALID_ARGUMENT)
+ return Empty()
+
+ try:
+ assert isinstance(request, ChannelpartitionConfig)
+ known_channel_partition_ref = dict(
+ (dt.data.channelpartition_ref, dt) for dt in self.root.get('/channel_pairs'))
+ known_channel_partition_ref_1 = dict(
+ (dt.data.parent_ref, dt) for dt in self.root.get('/v_ont_anis'))
+ reference = "channel pair"
+ assert request.name not in known_channel_partition_ref
+ reference = "vontani"
+ assert request.name not in known_channel_partition_ref_1
+ path = '/channel_partitions/{}'.format(request.name)
+ log.debug('removing-channel-partition', name=request.name)
+ self.root.remove(path)
+
+ return Empty()
+
+ except AssertionError:
+ context.set_details(
+ 'The channel partition -- \'{}\' is referenced by {}'.format(request.name, reference))
+ context.set_code(StatusCode.INVALID_ARGUMENT)
+ return Empty()
+
+ except KeyError:
+ context.set_details(
+ 'channel partition \'{}\' not found'.format(request.name))
+ context.set_code(StatusCode.NOT_FOUND)
+ return Empty()
+
+ def get_all_channel_pair_config(self, request, context):
+ log.info('grpc-request', request=request)
+ items = self.root.get('/channel_pairs')
+ return AllChannelpairConfig(channelpair_config=items)
+
+ def create_channel_pair(self, request, context):
+ log.info('grpc-request', request=request)
+
+ try:
+ assert isinstance(request, ChannelpairConfig)
+ assert self.validate_interface(request, context)
+ log.debug('creating-channel-pair', name=request.name)
+ self.root.add('/channel_pairs', request)
+
+ return Empty()
+ except AssertionError, e:
+ return Empty()
+ except ValueError:
+ context.set_details(
+ 'Duplicated channel pair \'{}\' cannot be created'.format(request.name))
+ context.set_code(StatusCode.INVALID_ARGUMENT)
+ return Empty()
+
+ def update_channel_pair(self, request, context):
+ log.info('grpc-request', request=request)
+
+ if '/' in request.name:
+ context.set_details(
+ 'Malformed name \'{}\''.format(request.name))
+ context.set_code(StatusCode.INVALID_ARGUMENT)
+ return ChannelpairConfig()
+
+ try:
+ assert isinstance(request, ChannelpairConfig)
+ assert self.validate_interface(request, context)
+
+ path = '/channel_pairs/{}'.format(request.name)
+ log.debug('updating-channel-pair', name=request.name)
+ self.root.update(path, request, strict=True)
+ return Empty()
+
+ except AssertionError, e:
+ return Empty()
+
+ except KeyError:
+ context.set_details(
+ 'channel pair \'{}\' not found'.format(request.name))
+ context.set_code(StatusCode.NOT_FOUND)
+ return Empty()
+
+ def delete_channel_pair(self, request, context):
+ log.info('grpc-request', request=request)
+
+ if '/' in request.name:
+ context.set_details(
+ 'Malformed name \'{}\''.format(request.name))
+ context.set_code(StatusCode.INVALID_ARGUMENT)
+ return Empty()
+
+ try:
+ assert isinstance(request, ChannelpairConfig)
+ device_items = self.root.get('/devices')
+ for device_item in device_items:
+ known_channel_pair_ref = dict(
+ (dt.data.channelpair_ref, dt) for dt in self.root.get(
+ '/devices/{}/channel_terminations'.format(device_item.id)))
+ assert request.name not in known_channel_pair_ref
+ path = '/channel_pairs/{}'.format(request.name)
+ log.debug('removing-channel-pair', name=request.name)
+ self.root.remove(path)
+
+ return Empty()
+
+ except AssertionError:
+ context.set_details(
+ 'The channel pair -- \'{}\' is referenced by channel termination'.format(request.name))
+ context.set_code(StatusCode.INVALID_ARGUMENT)
+ return Empty()
+
+ except KeyError:
+ context.set_details(
+ 'channel pair \'{}\' not found'.format(request.name))
+ context.set_code(StatusCode.NOT_FOUND)
+ return Empty()
+
+ def get_all_channel_termination_config(self, request, context):
+ log.info('grpc-request', request=request)
+ if '/' in request.id:
+ context.set_details(
+ 'Malformed device id \'{}\''.format(request.id))
+ context.set_code(StatusCode.INVALID_ARGUMENT)
+ return AllChannelterminationConfig()
+
+ try:
+ items = self.root.get(
+ '/devices/{}/channel_terminations'.format(request.id))
+ return AllChannelterminationConfig(channeltermination_config=items)
+ except KeyError:
+ context.set_details(
+ 'Device \'{}\' not found'.format(request.id))
+ context.set_code(StatusCode.NOT_FOUND)
+ return AllChannelterminationConfig()
+
+ def create_channel_termination(self, request, context):
+ log.info('grpc-request', request=request)
+
+ try:
+ assert isinstance(request, ChannelterminationConfig)
+ assert self.validate_interface(request, context)
+ #device = self.root.get('/devices/{}'.format(request.id))
+ except AssertionError, e:
+ return Empty()
+ except KeyError:
+ context.set_details(
+ 'Device \'{}\' not found'.format(request.id))
+ context.set_code(StatusCode.NOT_FOUND)
+ return Empty()
+ try:
+ path = '/devices/{}/channel_terminations'.format(request.id)
+ log.debug('creating-channel-termination', name=request.name)
+ self.root.add(path, request)
+ return Empty()
+ except KeyError:
+ context.set_details(
+ 'Device \'{}\' not activated'.format(request.id))
+ context.set_code(StatusCode.NOT_FOUND)
+ return Empty()
+ except ValueError:
+ context.set_details(
+ 'Duplicated channel termination \'{}\' cannot be created'.format(request.name))
+ context.set_code(StatusCode.INVALID_ARGUMENT)
+ return Empty()
+
+ def update_channel_termination(self, request, context):
+ log.info('grpc-request', request=request)
+
+ if '/' in request.name:
+ context.set_details(
+ 'Malformed name \'{}\''.format(request.name))
+ context.set_code(StatusCode.INVALID_ARGUMENT)
+ return ChannelterminationConfig()
+
+ try:
+ assert isinstance(request, ChannelterminationConfig)
+ assert self.validate_interface(request, context)
+ except AssertionError, e:
+ return Empty()
+ except KeyError:
+ context.set_details(
+ 'Device \'{}\' not found'.format(request.id))
+ context.set_code(StatusCode.NOT_FOUND)
+ return Empty()
+
+ try:
+ path = '/devices/{}/channel_terminations/{}'.format(request.id, request.name)
+ log.debug('updating-channel-termination', name=request.name)
+ self.root.update(path, request, strict=True)
+ return Empty()
+
+ except KeyError:
+ context.set_details(
+ 'channel termination \'{}\' not found'.format(request.name))
+ context.set_code(StatusCode.NOT_FOUND)
+ return Empty()
+
+ def delete_channel_termination(self, request, context):
+ log.info('grpc-request', request=request)
+
+ if '/' in request.id:
+ context.set_details(
+ 'Malformed device id \'{}\''.format(request.id))
+ context.set_code(StatusCode.INVALID_ARGUMENT)
+ return Empty()
+
+ if '/' in request.name:
+ context.set_details(
+ 'Malformed name \'{}\''.format(request.name))
+ context.set_code(StatusCode.INVALID_ARGUMENT)
+ return Empty()
+
+ try:
+ assert isinstance(request, ChannelterminationConfig)
+ except AssertionError:
+ context.set_details(
+ 'Instance is not of channel termination')
+ context.set_code(StatusCode.INVALID_ARGUMENT)
+ return Empty()
+ except KeyError:
+ context.set_details(
+ 'Device \'{}\' not found'.format(request.id))
+ context.set_code(StatusCode.NOT_FOUND)
+ return Empty()
+ try:
+ path = '/devices/{}/channel_terminations/{}'.format(request.id, request.name)
+ except KeyError:
+ context.set_details(
+ 'channel termination \'{}\' not found'.format(request.name))
+ context.set_code(StatusCode.NOT_FOUND)
+ return Empty()
+ try:
+ log.debug('removing-channel-termination', name=request.name)
+ self.root.remove(path)
+ return Empty()
+
+ except KeyError:
+ context.set_details(
+ 'Could not delete channel termination \'{}\''.format(request.name))
+ context.set_code(StatusCode.INVALID_ARGUMENT)
+ return Empty()
+
+ def get_all_ont_ani_config(self, request, context):
+ log.info('grpc-request', request=request)
+ items = self.root.get('/ont_anis')
+ return AllOntaniConfig(ontani_config=items)
+
+ def create_ont_ani(self, request, context):
+ log.info('grpc-request', request=request)
+
+ try:
+ assert isinstance(request, OntaniConfig)
+ assert self.validate_interface(request, context)
+ log.debug('creating-ont-ani', name=request.name)
+ self.root.add('/ont_anis', request)
+ return Empty()
+ except AssertionError, e:
+ return Empty()
+ except KeyError:
+ context.set_details(
+ 'Cannot create ontani \'{}\''.format(request.name))
+ context.set_code(StatusCode.NOT_FOUND)
+ return Empty()
+ except ValueError:
+ context.set_details(
+ 'Duplicated ontani \'{}\' cannot be created'.format(request.name))
+ context.set_code(StatusCode.INVALID_ARGUMENT)
+ return Empty()
+
+ def update_ont_ani(self, request, context):
+ log.info('grpc-request', request=request)
+
+ if '/' in request.name:
+ context.set_details(
+ 'Malformed name \'{}\''.format(request.name))
+ context.set_code(StatusCode.INVALID_ARGUMENT)
+ return OntaniConfig()
+
+ try:
+ assert isinstance(request, OntaniConfig)
+ assert self.validate_interface(request, context)
+
+ path = '/ont_anis/{}'.format(request.name)
+ log.debug('updating-ont-ani', name=request.name)
+ self.root.update(path, request, strict=True)
+ return Empty()
+
+ except AssertionError, e:
+ return Empty()
+
+ except KeyError:
+ context.set_details(
+ 'ontani \'{}\' not found'.format(request.name))
+ context.set_code(StatusCode.NOT_FOUND)
+ return Empty()
+
+ def delete_ont_ani(self, request, context):
+ log.info('grpc-request', request=request)
+
+ if '/' in request.name:
+ context.set_details(
+ 'Malformed name \'{}\''.format(request.name))
+ context.set_code(StatusCode.INVALID_ARGUMENT)
+ return Empty()
+
+ try:
+ assert isinstance(request, OntaniConfig)
+
+ path = '/ont_anis/{}'.format(request.name)
+ log.debug('removing-ont-ani', name=request.name)
+ self.root.remove(path)
+ return Empty()
+
+ except AssertionError:
+ context.set_details(
+ 'Instance is not of ont ani')
+ context.set_code(StatusCode.INVALID_ARGUMENT)
+ return Empty()
+
+ except KeyError:
+ context.set_details(
+ 'ontani \'{}\' not found'.format(request.name))
+ context.set_code(StatusCode.NOT_FOUND)
+ return Empty()
+
+ def get_all_v_ont_ani_config(self, request, context):
+ log.info('grpc-request', request=request)
+ items = self.root.get('/v_ont_anis')
+ return AllVOntaniConfig(v_ontani_config=items)
+
+ def create_v_ont_ani(self, request, context):
+ log.info('grpc-request', request=request)
+
+ try:
+ assert isinstance(request, VOntaniConfig)
+ assert self.validate_interface(request, context)
+ log.debug('creating-vont-ani', name=request.name)
+ self.root.add('/v_ont_anis', request)
+ return Empty()
+ except AssertionError, e:
+ return Empty()
+ except KeyError:
+ context.set_details(
+ 'Cannot create vontani \'{}\''.format(request.name))
+ context.set_code(StatusCode.NOT_FOUND)
+ return Empty()
+ except ValueError:
+ context.set_details(
+ 'Duplicated vontani \'{}\' cannot be created'.format(request.name))
+ context.set_code(StatusCode.INVALID_ARGUMENT)
+ return Empty()
+
+ def update_v_ont_ani(self, request, context):
+ log.info('grpc-request', request=request)
+
+ if '/' in request.name:
+ context.set_details(
+ 'Malformed name \'{}\''.format(request.name))
+ context.set_code(StatusCode.INVALID_ARGUMENT)
+ return VOntaniConfig()
+
+ try:
+ assert isinstance(request, VOntaniConfig)
+ assert self.validate_interface(request, context)
+
+ path = '/v_ont_anis/{}'.format(request.name)
+ log.debug('updating-vont-ani', name=request.name)
+ self.root.update(path, request, strict=True)
+ return Empty()
+
+ except AssertionError, e:
+ return Empty()
+
+ except KeyError:
+ context.set_details(
+ 'vontani \'{}\' not found'.format(request.name))
+ context.set_code(StatusCode.NOT_FOUND)
+ return Empty()
+
+ def delete_v_ont_ani(self, request, context):
+ log.info('grpc-request', request=request)
+
+ if '/' in request.name:
+ context.set_details(
+ 'Malformed name \'{}\''.format(request.name))
+ context.set_code(StatusCode.INVALID_ARGUMENT)
+ return Empty()
+
+ try:
+ assert isinstance(request, VOntaniConfig)
+ known_v_ont_ani_ref = dict(
+ (dt.data.v_ontani_ref, dt) for dt in self.root.get('/v_enets'))
+ assert request.name not in known_v_ont_ani_ref
+
+ path = '/v_ont_anis/{}'.format(request.name)
+ log.debug('removing-vont-ani', name=request.name)
+ self.root.remove(path)
+
+ return Empty()
+
+ except AssertionError:
+ context.set_details(
+ 'The vont ani -- \'{}\' is referenced by venet'.format(request.name))
+ context.set_code(StatusCode.INVALID_ARGUMENT)
+ return Empty()
+
+ except KeyError:
+ context.set_details(
+ 'vontani \'{}\' not found'.format(request.name))
+ context.set_code(StatusCode.NOT_FOUND)
+ return Empty()
+
+ def get_all_v_enet_config(self, request, context):
+ log.info('grpc-request', request=request)
+ items = self.root.get('/v_enets')
+ return AllVEnetConfig(v_enet_config=items)
+
+ def create_v_enet(self, request, context):
+ log.info('grpc-request', request=request)
+
+ try:
+ assert isinstance(request, VEnetConfig)
+ assert self.validate_interface(request, context)
+ log.debug('creating-venet', name=request.name)
+ self.root.add('/v_enets', request)
+ return Empty()
+ except AssertionError, e:
+ return Empty()
+ except KeyError:
+ context.set_details(
+ 'Cannot create venet \'{}\''.format(request.name))
+ context.set_code(StatusCode.NOT_FOUND)
+ return Empty()
+ except ValueError:
+ context.set_details(
+ 'Duplicated venet \'{}\' cannot be created'.format(request.name))
+ context.set_code(StatusCode.INVALID_ARGUMENT)
+ return Empty()
+
+ def update_v_enet(self, request, context):
+ log.info('grpc-request', request=request)
+
+ if '/' in request.name:
+ context.set_details(
+ 'Malformed name \'{}\''.format(request.name))
+ context.set_code(StatusCode.INVALID_ARGUMENT)
+ return VEnetConfig()
+
+ try:
+ assert isinstance(request, VEnetConfig)
+ assert self.validate_interface(request, context)
+
+ path = '/v_enets/{}'.format(request.name)
+ log.debug('updating-venet', name=request.name)
+ self.root.update(path, request, strict=True)
+ return Empty()
+
+ except AssertionError, e:
+ return Empty()
+
+ except KeyError:
+ context.set_details(
+ 'venet \'{}\' not found'.format(request.name))
+ context.set_code(StatusCode.NOT_FOUND)
+ return Empty()
+
+ def delete_v_enet(self, request, context):
+ log.info('grpc-request', request=request)
+
+ if '/' in request.name:
+ context.set_details(
+ 'Malformed name \'{}\''.format(request.name))
+ context.set_code(StatusCode.INVALID_ARGUMENT)
+ return Empty()
+
+ try:
+ assert isinstance(request, VEnetConfig)
+ #assert device.admin_state == AdminState.DISABLED, \
+ #'Device to delete cannot be ' \
+ #'in admin state \'{}\''.format(device.admin_state)
+ path = '/v_enets/{}'.format(request.name)
+ log.debug('removing-venet', name=request.name)
+ self.root.remove(path)
+ return Empty()
+
+ except AssertionError:
+ context.set_details(
+ 'Instance is not of venet')
+ context.set_code(StatusCode.INVALID_ARGUMENT)
+ return Empty()
+
+ except KeyError:
+ context.set_details(
+ 'venet \'{}\' not found'.format(request.name))
+ context.set_code(StatusCode.NOT_FOUND)
+ return Empty()
+
+ def validate_interface(self, request, context):
+ try:
+ if(isinstance(request, ChannelgroupConfig)):
+ assert isinstance(request, ChannelgroupConfig)
+ channelgroup = request
+ assert channelgroup.name != '', 'Channel Group name is mandatory'
+ assert 0 <= channelgroup.data.polling_period <= 864000, \
+ 'Channel Group polling period must be in range of [1, 864000]'
+ return True
+ elif(isinstance(request, ChannelpartitionConfig)):
+ assert isinstance(request, ChannelpartitionConfig)
+ channelpartition = request
+ assert channelpartition.name != '', 'Channel Partition name is mandatory'
+
+ assert channelpartition.data.channelgroup_ref != '', \
+ 'Channel Partition must reference a channel group'
+ assert self.get_ref_data(request, context, "channel_groups", request.data.channelgroup_ref), \
+ 'Reference to channel group -- \'{}\' not found'.format(request.data.channelgroup_ref)
+
+ assert 0 <= channelpartition.data.closest_ont_distance <= 40, \
+ 'Channel Partition closest ont distance must be in range of [0, 40]'
+
+ assert channelpartition.data.differential_fiber_distance == 0 or \
+ channelpartition.data.differential_fiber_distance == 20 or \
+ channelpartition.data.differential_fiber_distance == 34 or \
+ channelpartition.data.differential_fiber_distance == 40, \
+ 'Channel Partition differential fiber distance must be [20 | 34 | 40]'
+ return True
+ elif(isinstance(request, ChannelpairConfig)):
+ assert isinstance(request, ChannelpairConfig)
+ channelpair = request
+ channelpair_type = ["channelpair", "channelpair_xgs"]
+ channelpair_speed_type = ["unplanned_cp_speed", "down_10_up_10", "down_10_up_2_5", "down_2_5_up_2_5"]
+ assert channelpair.name != '', 'Channel Pair name is mandatory'
+
+ if channelpair.data.channelgroup_ref:
+ assert self.get_ref_data(request, context, "channel_groups", request.data.channelgroup_ref), \
+ 'Reference to channel group -- \'{}\' not found'\
+ .format(request.data.channelgroup_ref)
+ if channelpair.data.channelpartition_ref:
+ assert self.get_ref_data(request, context, "channel_partitions", request.data.channelpartition_ref), \
+ 'Reference to channel partition -- \'{}\' not found'\
+ .format(request.data.channelpartition_ref)
+
+ assert channelpair.data.channelpair_type != '', 'Channel Pair type is mandatory'
+ assert channelpair.data.channelpair_type in channelpair_type, \
+ 'Invalid value for Channel Pair type \'{}\''.format(channelpair.data.channelpair_type)
+ assert channelpair.data.channelpair_linerate in channelpair_speed_type, \
+ 'Invalid value for Channel Pair linerate \'{}\''.format(channelpair.data.channelpair_linerate)
+ return True
+ elif(isinstance(request, ChannelterminationConfig)):
+ assert isinstance(request, ChannelterminationConfig)
+ channeltermin = request
+ assert '/' not in channeltermin.id, 'Malformed device id \'{}\''.format(request.id)
+ assert channeltermin.id != '', 'Device ID is mandatory'
+ assert channeltermin.name != '', 'Channel Termination name is mandatory'
+
+ if channeltermin.data.channelpair_ref:
+ assert self.get_ref_data(request, context, "channel_pairs", request.data.channelpair_ref), \
+ 'Reference to channel pair -- \'{}\' not found'.format(request.data.channelpair_ref)
+
+ assert 0 <= channeltermin.data.ber_calc_period <= 864000, \
+ 'Channel Termination ber calc period must be in range of [1, 864000]'
+ return True
+ elif(isinstance(request, OntaniConfig)):
+ assert isinstance(request, OntaniConfig)
+ ontani = request
+ assert ontani.name != '', 'OntAni name is mandatory'
+ return True
+ elif(isinstance(request, VOntaniConfig)):
+ assert isinstance(request, VOntaniConfig)
+ vontani = request
+ assert vontani.name != '', 'VOntAni name is mandatory'
+
+ if vontani.data.parent_ref:
+ assert self.get_ref_data(request, context, "channel_partitions", request.data.parent_ref), \
+ 'Reference to channel partition -- \'{}\' not found'.format(request.data.parent_ref)
+ if vontani.data.preferred_chanpair:
+ assert self.get_ref_data(request, context, "channel_pairs", request.data.preferred_chanpair), \
+ 'Preferred channel pair -- \'{}\' not found'.format(request.data.preferred_chanpair)
+ if vontani.data.protection_chanpair:
+ assert self.get_ref_data(request, context, "channel_pairs", request.data.protection_chanpair), \
+ 'Protection channel pair -- \'{}\' not found'.format(request.data.protection_chanpair)
+
+ assert 0 <= len(vontani.data.expected_registration_id) <= 36, \
+ 'VOnt Ani expected registration id string length must be in range of [0, 36]'
+ assert 0 <= vontani.data.onu_id <= 1020, \
+ 'VOnt Ani ONU id must be in range of [0, 1020]'
+
+ items = self.root.get('/v_ont_anis')
+ for item in items:
+ if item.data.parent_ref == vontani.data.parent_ref or \
+ item.data.preferred_chanpair == vontani.data.preferred_chanpair or \
+ item.data.protection_chanpair == vontani.data.protection_chanpair:
+ assert item.data.onu_id != vontani.data.onu_id, \
+ 'VOnt Ani ONU id -- \'{}\' already exists, but must be unique within channel group'.format(vontani.data.onu_id)
+ return True
+ elif(isinstance(request, VEnetConfig)):
+ assert isinstance(request, VEnetConfig)
+ venet = request
+ assert venet.name != '', 'VEnet name is mandatory'
+
+ if venet.data.v_ontani_ref:
+ assert self.get_ref_data(request, context, "v_ont_anis", venet.data.v_ontani_ref), \
+ 'Reference to ont ani -- \'{}\' not found'.format(venet.data.v_ontani_ref)
+ return True
+ else:
+ return False
+ except AssertionError, e:
+ context.set_details(e.message)
+ context.set_code(StatusCode.INVALID_ARGUMENT)
+ return False
+
+ def get_ref_data(self, request, context, interface, reference):
+ depth = int(dict(context.invocation_metadata()).get('get-depth', 0))
+
+ try:
+ path = '/{}/'.format(interface)
+ self.root.get(path + reference, depth=depth)
+ log.info('reference-for-{}-found-\'{}\''.format(interface, reference))
+ return True
+
+ except KeyError:
+ log.info('reference-for-{}-not-found-\'{}\''.format(interface, reference))
+ return False
diff --git a/voltha/protos/bbf_fiber.proto b/voltha/protos/bbf_fiber.proto
new file mode 100644
index 0000000..65a3f78
--- /dev/null
+++ b/voltha/protos/bbf_fiber.proto
@@ -0,0 +1,14 @@
+/*
+TOP Level BBF Fiber proto
+*/
+
+syntax = "proto3";
+package bbf_fiber;
+import "bbf_fiber_base.proto";
+import "bbf_fiber_wavelength_profile_body.proto";
+import "bbf_fiber_channelgroup_body.proto";
+import "bbf_fiber_channelpartition_body.proto";
+import "bbf_fiber_channelpair_body.proto";
+import "bbf_fiber_channeltermination_body.proto";
+import "bbf_fiber_ontani_body.proto";
+import "bbf_fiber_v_ontani_body.proto";
diff --git a/voltha/protos/bbf_fiber_base.proto b/voltha/protos/bbf_fiber_base.proto
new file mode 100644
index 0000000..2c02171
--- /dev/null
+++ b/voltha/protos/bbf_fiber_base.proto
@@ -0,0 +1,111 @@
+syntax = "proto3";
+package bbf_fiber;
+
+import public "meta.proto";
+import "ietf_interfaces.proto";
+import "bbf_fiber_channelgroup_body.proto";
+import "bbf_fiber_channelpartition_body.proto";
+import "bbf_fiber_channelpair_body.proto";
+import "bbf_fiber_channeltermination_body.proto";
+import "bbf_fiber_ontani_body.proto";
+import "bbf_fiber_v_ontani_body.proto";
+import "bbf_fiber_v_enet_body.proto";
+
+message ChannelgroupConfig
+{
+ ietf_interfaces.Interface interface = 1;
+ ChannelgroupConfigData data = 2;
+ string name = 3;
+
+}
+
+message ChannelpartitionConfig
+{
+ ietf_interfaces.Interface interface = 1;
+ ChannelpartitionConfigData data = 2;
+ string name = 3;
+}
+
+message ChannelpairConfig
+{
+ ietf_interfaces.Interface interface = 1;
+ ChannelpairConfigData data = 2;
+ string name = 3;
+}
+message ChannelpairOper
+{
+ ietf_interfaces.Interface interface = 1;
+ ChannelpairOperData operdata = 2;
+ string name = 3;
+}
+
+message ChannelterminationConfig
+{
+ string id = 1; // To work around a chameleon POST bug
+ ietf_interfaces.Interface interface = 2;
+ ChannelterminationConfigData data = 3;
+ string name = 4;
+}
+message ChannelterminationOper
+{
+ ietf_interfaces.Interface interface = 1;
+ ChannelterminationOperData data = 2;
+ string name = 3;
+}
+
+
+message OntaniConfig
+{
+ ietf_interfaces.Interface interface = 1;
+ OntaniConfigData data = 2;
+ string name = 3;
+}
+message OntaniOper
+{
+ ietf_interfaces.Interface interface = 1;
+ OntaniOperData data = 2;
+ string name = 3;
+}
+
+message VOntaniConfig
+{
+ ietf_interfaces.Interface interface = 1;
+ VOntaniConfigData data = 2;
+ string name = 3;
+}
+
+message VEnetConfig
+{
+ ietf_interfaces.Interface interface = 1;
+ VEnetConfigData data = 2;
+ string name = 3;
+}
+
+message AllChannelgroupConfig
+{
+ repeated ChannelgroupConfig channelgroup_config = 1 [(voltha.child_node) = {key: "name"}];
+}
+message AllChannelpartitionConfig
+{
+ repeated ChannelpartitionConfig channelpartition_config = 1 [(voltha.child_node) = {key: "name"}];
+}
+message AllChannelpairConfig
+{
+ repeated ChannelpairConfig channelpair_config = 1 [(voltha.child_node) = {key: "name"}];
+}
+message AllChannelterminationConfig
+{
+ repeated ChannelterminationConfig channeltermination_config = 1 [(voltha.child_node) = {key: "name"}];
+}
+message AllOntaniConfig
+{
+ repeated OntaniConfig ontani_config = 1 [(voltha.child_node) = {key: "name"}];
+}
+message AllVOntaniConfig
+{
+ repeated VOntaniConfig v_ontani_config = 1 [(voltha.child_node) = {key: "name"}];
+}
+message AllVEnetConfig
+{
+ repeated VEnetConfig v_enet_config = 1 [(voltha.child_node) = {key: "name"}];
+}
diff --git a/voltha/protos/bbf_fiber_channelgroup_body.proto b/voltha/protos/bbf_fiber_channelgroup_body.proto
new file mode 100644
index 0000000..2eecc24
--- /dev/null
+++ b/voltha/protos/bbf_fiber_channelgroup_body.proto
@@ -0,0 +1,10 @@
+syntax = "proto3";
+package bbf_fiber;
+import public "meta.proto";
+import "bbf_fiber_types.proto";
+
+message ChannelgroupConfigData {
+ uint32 polling_period = 1;
+ bbf_fiber_types.RamanMitigationType raman_mitigation = 2;
+ string system_id = 3 ;
+}
diff --git a/voltha/protos/bbf_fiber_channelpair_body.proto b/voltha/protos/bbf_fiber_channelpair_body.proto
new file mode 100644
index 0000000..a66996b
--- /dev/null
+++ b/voltha/protos/bbf_fiber_channelpair_body.proto
@@ -0,0 +1,18 @@
+syntax = "proto3";
+package bbf_fiber;
+import "bbf_fiber_types.proto";
+
+message ChannelpairConfigData {
+ string channelgroup_ref = 1 ;
+ string channelpartition_ref = 2 ;
+ string channelpair_type = 3 ;
+ string channelpair_linerate = 4 ;
+ uint32 gpon_ponid_interval = 5 ;
+ bbf_fiber_types.PonIdOdnClassType gpon_ponid_odn_class = 6;
+}
+message ChannelpairOperData {
+ uint32 actual_downstream_lambda = 1 ;
+ bool primary_ct_assigned = 2 ;
+ bool secondary_ct_assigned = 3 ;
+}
+
diff --git a/voltha/protos/bbf_fiber_channelpartition_body.proto b/voltha/protos/bbf_fiber_channelpartition_body.proto
new file mode 100644
index 0000000..0134b35
--- /dev/null
+++ b/voltha/protos/bbf_fiber_channelpartition_body.proto
@@ -0,0 +1,12 @@
+syntax = "proto3";
+package bbf_fiber;
+import "bbf_fiber_types.proto";
+
+message ChannelpartitionConfigData {
+ string channelgroup_ref = 1 ;
+ bool fec_downstream = 2;
+ uint32 closest_ont_distance = 3;
+ uint32 differential_fiber_distance = 4;
+ bbf_fiber_types.AuthMethodType authentication_method = 5;
+ bool multicast_aes_indicator = 7;
+}
diff --git a/voltha/protos/bbf_fiber_channeltermination_body.proto b/voltha/protos/bbf_fiber_channeltermination_body.proto
new file mode 100644
index 0000000..2f921d5
--- /dev/null
+++ b/voltha/protos/bbf_fiber_channeltermination_body.proto
@@ -0,0 +1,21 @@
+syntax = "proto3";
+package bbf_fiber;
+
+message ChannelterminationConfigData {
+ string channelpair_ref = 1 ;
+ bool meant_for_type_b_primary_role = 2 ;
+ uint32 ngpon2_twdm_admin_label = 3 ;
+ uint32 ngpon2_ptp_admin_label = 4 ;
+ uint32 xgs_ponid = 5 ;
+ uint32 xgpon_ponid = 6 ;
+ string gpon_ponid = 7 ;
+ string pon_tag = 8 ;
+ uint32 ber_calc_period = 9 ;
+ string location = 10 ;
+ string url_to_reach = 11 ;
+}
+message ChannelterminationOperData {
+ string ponid_display = 1 ;
+ string type_b_state = 2 ;
+}
+
diff --git a/voltha/protos/bbf_fiber_ontani_body.proto b/voltha/protos/bbf_fiber_ontani_body.proto
new file mode 100644
index 0000000..35d1d69
--- /dev/null
+++ b/voltha/protos/bbf_fiber_ontani_body.proto
@@ -0,0 +1,11 @@
+syntax = "proto3";
+package bbf_fiber;
+
+message OntaniConfigData {
+ bool upstream_fec_indicator = 1 ;
+ bool mgnt_gemport_aes_indicator = 2 ;
+}
+message OntaniOperData {
+ uint32 onu_id = 1 ;
+ uint32 channel_partition_id = 2 ;
+}
diff --git a/voltha/protos/bbf_fiber_types.proto b/voltha/protos/bbf_fiber_types.proto
new file mode 100644
index 0000000..119ced0
--- /dev/null
+++ b/voltha/protos/bbf_fiber_types.proto
@@ -0,0 +1,50 @@
+syntax = "proto3";
+package bbf_fiber_types;
+
+enum AuthMethodType
+{
+ SERIAL_NUMBER = 0;
+ LOID = 1;
+ REGISTRATION_ID = 2;
+ OMCI = 3;
+ DOT1X = 4;
+
+}
+enum RamanMitigationType
+{
+ RAMAN_NONE = 0;
+ RAMAN_MILLER = 1;
+ RAMAN_8B10B = 2;
+
+}
+enum PonIdOdnClassType
+{
+ CLASS_A = 0;
+ CLASS_B = 1;
+ CLASS_B_PLUS = 2;
+ CLASS_C = 3;
+ CLASS_C_PLUS = 4;
+ CLASS_AUTO = 255;
+}
+enum ChannelpairSpeedType
+{
+ UNPLANNED_CP_SPEED = 0;
+ DOWN_10_UP_10 = 1;
+ DOWN_10_UP_2DOT5 = 2;
+ DOWN_2DOT5_UP_2DOT5 = 3;
+}
+enum ChannelpairType
+{
+ CHANNELPAIR = 0;
+ CHANNELPAIR_XGS = 1;
+}
+enum TypeBRoleType
+{
+ PRIMARY = 0;
+ SECONDARY = 1;
+}
+enum TypeBRoleStateType
+{
+ ACTIVE = 0;
+ STANDBY = 1;
+}
diff --git a/voltha/protos/bbf_fiber_v_enet_body.proto b/voltha/protos/bbf_fiber_v_enet_body.proto
new file mode 100644
index 0000000..603668c
--- /dev/null
+++ b/voltha/protos/bbf_fiber_v_enet_body.proto
@@ -0,0 +1,6 @@
+syntax = "proto3";
+package bbf_fiber;
+
+message VEnetConfigData {
+ string v_ontani_ref = 1 ;
+}
diff --git a/voltha/protos/bbf_fiber_v_ontani_body.proto b/voltha/protos/bbf_fiber_v_ontani_body.proto
new file mode 100644
index 0000000..665caf6
--- /dev/null
+++ b/voltha/protos/bbf_fiber_v_ontani_body.proto
@@ -0,0 +1,12 @@
+syntax = "proto3";
+package bbf_fiber;
+
+message VOntaniConfigData {
+ string parent_ref = 1 ;
+ string expected_serial_number = 2 ;
+ string expected_registration_id = 3 ;
+ string preferred_chanpair = 4 ;
+ string protection_chanpair = 5 ;
+ uint32 upstream_channel_speed = 6 ;
+ uint32 onu_id = 7 ;
+}
diff --git a/voltha/protos/bbf_fiber_wavelength_profile_body.proto b/voltha/protos/bbf_fiber_wavelength_profile_body.proto
new file mode 100644
index 0000000..5f25f85
--- /dev/null
+++ b/voltha/protos/bbf_fiber_wavelength_profile_body.proto
@@ -0,0 +1,14 @@
+syntax = "proto3";
+package bbf_fiber;
+import public "meta.proto";
+
+message WavelengthProfileData {
+ string name = 1 ;
+ uint32 upstream_channelid = 2 ;
+ uint32 downstream_channelid = 3 ;
+ uint32 downstream_wavelength = 4 ;
+}
+
+message WavelengthProfile {
+ repeated WavelengthProfileData wavelength_profile_data = 1 [(voltha.child_node) = {key: "name"}];
+}
diff --git a/voltha/protos/device.proto b/voltha/protos/device.proto
index b71063b..f7828e6 100644
--- a/voltha/protos/device.proto
+++ b/voltha/protos/device.proto
@@ -7,6 +7,7 @@
import "common.proto";
import "openflow_13.proto";
import "yang_options.proto";
+import "bbf_fiber_base.proto";
// A Device Type
message DeviceType {
@@ -204,6 +205,9 @@
// device to falicitata callbacks and to simplify manipulation.
PmConfigs pm_configs = 131 [(child_node) = {}];
+ // Channel Terminations for the OLT device
+ repeated bbf_fiber.ChannelterminationConfig channel_terminations = 132 [(child_node) = {key: "name"}];
+
}
message Devices {
diff --git a/voltha/protos/ietf_interfaces.proto b/voltha/protos/ietf_interfaces.proto
new file mode 100644
index 0000000..e3f1204
--- /dev/null
+++ b/voltha/protos/ietf_interfaces.proto
@@ -0,0 +1,50 @@
+syntax = "proto3";
+package ietf_interfaces;
+
+message Interfaces {
+ repeated Interface all_interfaces = 1;
+}
+message Interface {
+ string name = 1 ;
+ string description = 2 ;
+ string type = 3 ;
+ bool enabled = 4;
+ enum LinkUpDownTrapEnableType
+ {
+ TRAP_DISABLED = 0 ;
+ TRAP_ENABLED = 1 ;
+ }
+ LinkUpDownTrapEnableType link_up_down_trap_enable = 5;
+}
+
+message InterfacesState {
+ repeated InterfaceState all_interfacs = 1;
+}
+message InterfaceState {
+ string name = 1 ;
+ string type = 2 ;
+ enum AdminStatusType
+ {
+ ADMIN_DOWN = 0 ;
+ ADMIN_TESTING = 1 ;
+ ADMIN_UP = 2 ;
+ }
+ AdminStatusType admin_status = 3;
+ enum OperStatusType
+ {
+ DORMANT = 0 ;
+ LOWER_LAYER_DOWN = 1 ;
+ UNKNOWN = 2 ;
+ TESTING = 3 ;
+ UP = 4 ;
+ DOWN = 5 ;
+ NOT_PRESENT = 6 ;
+ }
+ OperStatusType oper_status = 4;
+ string last_change = 5 ;
+ int32 if_index = 6 ;
+ string phys_address = 7 ;
+ repeated string higher_layer_if = 8 ;
+ repeated string lower_layer_if = 9 ;
+ uint64 speed = 10 ;
+}
diff --git a/voltha/protos/ponsim.proto b/voltha/protos/ponsim.proto
index a3741a0..3ea7767 100644
--- a/voltha/protos/ponsim.proto
+++ b/voltha/protos/ponsim.proto
@@ -4,7 +4,7 @@
import "google/protobuf/empty.proto";
import "openflow_13.proto";
-
+import "bbf_fiber_base.proto";
message PonSimDeviceInfo {
int32 nni_port = 1;
@@ -31,6 +31,19 @@
repeated PonSimPortMetrics metrics = 2;
}
+message InterfaceConfig
+{
+ oneof interface_type
+ {
+ bbf_fiber.ChannelgroupConfig channel_group_config = 1;
+ bbf_fiber.ChannelpartitionConfig channel_partition_config = 2;
+ bbf_fiber.ChannelpairConfig channel_pair_config = 3;
+ bbf_fiber.ChannelterminationConfig channel_termination_config = 4;
+ bbf_fiber.OntaniConfig ont_ani_config = 5;
+ bbf_fiber.VOntaniConfig vont_ani_config = 6;
+ bbf_fiber.VEnetConfig venet_config = 7;
+ }
+}
service PonSim {
@@ -42,4 +55,17 @@
rpc GetStats(google.protobuf.Empty)
returns(PonSimMetrics) {}
+
+}
+
+service XPonSim
+{
+ rpc CreateInterface(InterfaceConfig)
+ returns(google.protobuf.Empty) {}
+
+ rpc UpdateInterface(InterfaceConfig)
+ returns(google.protobuf.Empty) {}
+
+ rpc RemoveInterface(InterfaceConfig)
+ returns(google.protobuf.Empty) {}
}
diff --git a/voltha/protos/voltha.proto b/voltha/protos/voltha.proto
index 1500bf1..b015f47 100644
--- a/voltha/protos/voltha.proto
+++ b/voltha/protos/voltha.proto
@@ -21,6 +21,8 @@
import public "device.proto";
import public "adapter.proto";
import public "openflow_13.proto";
+import "bbf_fiber.proto";
+import "bbf_fiber_base.proto";
option java_package = "org.opencord.voltha";
option java_outer_classname = "VolthaProtos";
@@ -90,6 +92,18 @@
repeated DeviceGroup device_groups = 15 [(child_node) = {key: "id"}];
repeated AlarmFilter alarm_filters = 16 [(child_node) = {key: "id"}];
+
+ repeated bbf_fiber.ChannelgroupConfig channel_groups = 17 [(child_node) = {key: "name"}];
+
+ repeated bbf_fiber.ChannelpartitionConfig channel_partitions = 18 [(child_node) = {key: "name"}];
+
+ repeated bbf_fiber.ChannelpairConfig channel_pairs = 19 [(child_node) = {key: "name"}];
+
+ repeated bbf_fiber.OntaniConfig ont_anis = 20 [(child_node) = {key: "name"}];
+
+ repeated bbf_fiber.VOntaniConfig v_ont_anis = 21 [(child_node) = {key: "name"}];
+
+ repeated bbf_fiber.VEnetConfig v_enets = 22 [(child_node) = {key: "name"}];
}
message VolthaInstances {
@@ -115,6 +129,17 @@
repeated DeviceGroup device_groups = 15 [(child_node) = {key: "id"}];
+ repeated bbf_fiber.ChannelgroupConfig channel_groups = 16 [(child_node) = {key: "name"}];
+
+ repeated bbf_fiber.ChannelpartitionConfig channel_partitions = 17 [(child_node) = {key: "name"}];
+
+ repeated bbf_fiber.ChannelpairConfig channel_pairs = 18 [(child_node) = {key: "name"}];
+
+ repeated bbf_fiber.OntaniConfig ont_anis = 19 [(child_node) = {key: "name"}];
+
+ repeated bbf_fiber.VOntaniConfig v_ont_anis = 20 [(child_node) = {key: "name"}];
+
+ repeated bbf_fiber.VEnetConfig v_enets = 21 [(child_node) = {key: "name"}];
}
// Device Self Test Response
@@ -377,6 +402,190 @@
};
}
+ // List all Channel Groups
+ rpc GetAllChannelgroupConfig(google.protobuf.Empty) returns(bbf_fiber.AllChannelgroupConfig) {
+ option (google.api.http) = {
+ get: "/api/v1/channel_groups"
+ };
+ }
+ // Create Channel Group
+ rpc CreateChannelgroup(bbf_fiber.ChannelgroupConfig) returns(google.protobuf.Empty) {
+ option (google.api.http) = {
+ post: "/api/v1/channel_groups/{name}"
+ body: "*"
+ };
+ }
+ // Update Channel Group
+ rpc UpdateChannelgroup(bbf_fiber.ChannelgroupConfig) returns(google.protobuf.Empty) {
+ option (google.api.http) = {
+ post: "/api/v1/channel_groups/{name}/modify"
+ body: "*"
+ };
+ }
+ // Delete Channel Group
+ rpc DeleteChannelgroup(bbf_fiber.ChannelgroupConfig) returns(google.protobuf.Empty) {
+ option (google.api.http) = {
+ delete: "/api/v1/channel_groups/{name}/delete"
+ };
+ }
+ // List all channel partitions
+ rpc GetAllChannelpartitionConfig(google.protobuf.Empty) returns(bbf_fiber.AllChannelpartitionConfig) {
+ option (google.api.http) = {
+ get: "/api/v1/channel_partitions"
+ };
+ }
+ // Create a channel partition
+ rpc CreateChannelpartition(bbf_fiber.ChannelpartitionConfig) returns(google.protobuf.Empty) {
+ option (google.api.http) = {
+ post: "/api/v1/channel_partitions/{name}"
+ body: "*"
+ };
+ }
+ // Update a channel partition
+ rpc UpdateChannelpartition(bbf_fiber.ChannelpartitionConfig) returns(google.protobuf.Empty) {
+ option (google.api.http) = {
+ post: "/api/v1/channel_partitions/{name}/modify"
+ body: "*"
+ };
+ }
+ // Delete a channel partition
+ rpc DeleteChannelpartition(bbf_fiber.ChannelpartitionConfig) returns(google.protobuf.Empty) {
+ option (google.api.http) = {
+ delete: "/api/v1/channel_partitions/{name}/delete"
+ };
+ }
+
+ // List all channel pairs managed by this Voltha instance
+ rpc GetAllChannelpairConfig(google.protobuf.Empty) returns(bbf_fiber.AllChannelpairConfig) {
+ option (google.api.http) = {
+ get: "/api/v1/channel_pairs"
+ };
+ }
+ // Create a channel pair
+ rpc CreateChannelpair(bbf_fiber.ChannelpairConfig) returns(google.protobuf.Empty) {
+ option (google.api.http) = {
+ post: "/api/v1/channel_pairs/{name}"
+ body: "*"
+ };
+ }
+ // Update a channel pair
+ rpc UpdateChannelpair(bbf_fiber.ChannelpairConfig) returns(google.protobuf.Empty) {
+ option (google.api.http) = {
+ post: "/api/v1/channel_pairs/{name}/modify"
+ body: "*"
+ };
+ }
+ // Delete a channel pair
+ rpc DeleteChannelpair(bbf_fiber.ChannelpairConfig) returns(google.protobuf.Empty) {
+ option (google.api.http) = {
+ delete: "/api/v1/channel_pairs/{name}/delete"
+ };
+ }
+ // List all channel terminations managed by this Voltha instance
+ rpc GetAllChannelterminationConfig(ID) returns(bbf_fiber.AllChannelterminationConfig) {
+ option (google.api.http) = {
+ get: "/api/v1/devices/{id}/channel_terminations"
+ };
+ }
+ // Create a channel termination
+ rpc CreateChanneltermination(bbf_fiber.ChannelterminationConfig) returns(google.protobuf.Empty) {
+ option (google.api.http) = {
+ post: "/api/v1/devices/{id}/channel_terminations/{name}"
+ body: "*"
+ };
+ }
+ // Update a channel termination
+ rpc UpdateChanneltermination(bbf_fiber.ChannelterminationConfig) returns(google.protobuf.Empty) {
+ option (google.api.http) = {
+ post: "/api/v1/devices/{id}/channel_terminations/{name}/modify"
+ body: "*"
+ };
+ }
+ // Delete a channel termination
+ rpc DeleteChanneltermination(bbf_fiber.ChannelterminationConfig) returns(google.protobuf.Empty) {
+ option (google.api.http) = {
+ delete: "/api/v1/devices/{id}/channel_terminations/{name}/delete"
+ };
+ }
+ // List all ont configs managed by this Voltha instance
+ rpc GetAllOntaniConfig(google.protobuf.Empty) returns(bbf_fiber.AllOntaniConfig) {
+ option (google.api.http) = {
+ get: "/api/v1/ont_anis"
+ };
+ }
+ // Create an ont configs
+ rpc CreateOntani(bbf_fiber.OntaniConfig) returns(google.protobuf.Empty) {
+ option (google.api.http) = {
+ post: "/api/v1/ont_anis/{name}"
+ body: "*"
+ };
+ }
+ // Update an ont configs
+ rpc UpdateOntani(bbf_fiber.OntaniConfig) returns(google.protobuf.Empty) {
+ option (google.api.http) = {
+ post: "/api/v1/ont_anis/{name}/modify"
+ body: "*"
+ };
+ }
+ // Delete an ont configs
+ rpc DeleteOntani(bbf_fiber.OntaniConfig) returns(google.protobuf.Empty) {
+ option (google.api.http) = {
+ delete: "/api/v1/ont_anis/{name}/delete"
+ };
+ }
+ // List all V ont configs managed by this Voltha instance
+ rpc GetAllVOntaniConfig(google.protobuf.Empty) returns(bbf_fiber.AllVOntaniConfig) {
+ option (google.api.http) = {
+ get: "/api/v1/v_ont_anis"
+ };
+ }
+ // Create a v ont configs
+ rpc CreateVOntani(bbf_fiber.VOntaniConfig) returns(google.protobuf.Empty) {
+ option (google.api.http) = {
+ post: "/api/v1/v_ont_anis/{name}"
+ body: "*"
+ };
+ }
+ // Update a v ont configs
+ rpc UpdateVOntani(bbf_fiber.VOntaniConfig) returns(google.protobuf.Empty) {
+ option (google.api.http) = {
+ post: "/api/v1/v_ont_anis/{name}/modify"
+ body: "*"
+ };
+ }
+ // Delete a v ont configs
+ rpc DeleteVOntani(bbf_fiber.VOntaniConfig) returns(google.protobuf.Empty) {
+ option (google.api.http) = {
+ delete: "/api/v1/v_ont_anis/{name}/delete"
+ };
+ }
+ // List all venet configs managed by this Voltha instance
+ rpc GetAllVEnetConfig(google.protobuf.Empty) returns(bbf_fiber.AllVEnetConfig) {
+ option (google.api.http) = {
+ get: "/api/v1/v_enets"
+ };
+ }
+ // Create venet configs
+ rpc CreateVEnet(bbf_fiber.VEnetConfig) returns(google.protobuf.Empty) {
+ option (google.api.http) = {
+ post: "/api/v1/v_enets/{name}"
+ body: "*"
+ };
+ }
+ // Update venet configs
+ rpc UpdateVEnet(bbf_fiber.VEnetConfig) returns(google.protobuf.Empty) {
+ option (google.api.http) = {
+ post: "/api/v1/v_enets/{name}/modify"
+ body: "*"
+ };
+ }
+ // Delete venet configs
+ rpc DeleteVEnet(bbf_fiber.VEnetConfig) returns(google.protobuf.Empty) {
+ option (google.api.http) = {
+ delete: "/api/v1/v_enets/{name}/delete"
+ };
+ }
+
rpc GetImages(ID) returns(Images) {
option (google.api.http) = {
get: "/api/v1/devices/{id}/images"
@@ -603,7 +812,189 @@
get: "/api/v1/local/device_groups/{id}"
};
}
+ // List all channel groups managed by this Voltha instance
+ rpc GetAllChannelgroupConfig(google.protobuf.Empty) returns(bbf_fiber.AllChannelgroupConfig) {
+ option (google.api.http) = {
+ get: "/api/v1/local/channel_groups"
+ };
+ }
+ // Create a channel group
+ rpc CreateChannelgroup(bbf_fiber.ChannelgroupConfig) returns(google.protobuf.Empty) {
+ option (google.api.http) = {
+ post: "/api/v1/local/channel_groups/{name}"
+ body: "*"
+ };
+ }
+ // Update a channel group
+ rpc UpdateChannelgroup(bbf_fiber.ChannelgroupConfig) returns(google.protobuf.Empty) {
+ option (google.api.http) = {
+ post: "/api/v1/local/channel_groups/{name}/modify"
+ body: "*"
+ };
+ }
+ // Delate a channel group
+ rpc DeleteChannelgroup(bbf_fiber.ChannelgroupConfig) returns(google.protobuf.Empty) {
+ option (google.api.http) = {
+ delete: "/api/v1/local/channel_groups/{name}/delete"
+ };
+ }
+ // List all channel partitions managed by this Voltha instance
+ rpc GetAllChannelpartitionConfig(google.protobuf.Empty) returns(bbf_fiber.AllChannelpartitionConfig) {
+ option (google.api.http) = {
+ get: "/api/v1/local/channel_partitions"
+ };
+ }
+ // Create a channel partition
+ rpc CreateChannelpartition(bbf_fiber.ChannelpartitionConfig) returns(google.protobuf.Empty) {
+ option (google.api.http) = {
+ post: "/api/v1/local/channel_partitions/{name}"
+ body: "*"
+ };
+ }
+ // Update a channel partition
+ rpc UpdateChannelpartition(bbf_fiber.ChannelpartitionConfig) returns(google.protobuf.Empty) {
+ option (google.api.http) = {
+ post: "/api/v1/local/channel_partitions/{name}/modify"
+ body: "*"
+ };
+ }
+ // Delete a channel partition
+ rpc DeleteChannelpartition(bbf_fiber.ChannelpartitionConfig) returns(google.protobuf.Empty) {
+ option (google.api.http) = {
+ delete: "/api/v1/local/channel_partitions/{name}/delete"
+ };
+ }
+ // List all channel pairs managed by this Voltha instance
+ rpc GetAllChannelpairConfig(google.protobuf.Empty) returns(bbf_fiber.AllChannelpairConfig) {
+ option (google.api.http) = {
+ get: "/api/v1/local/channel_pairs"
+ };
+ }
+ // Create a channel pair
+ rpc CreateChannelpair(bbf_fiber.ChannelpairConfig) returns(google.protobuf.Empty) {
+ option (google.api.http) = {
+ post: "/api/v1/local/channel_pairs/{name}"
+ body: "*"
+ };
+ }
+ // Update a channel pair
+ rpc UpdateChannelpair(bbf_fiber.ChannelpairConfig) returns(google.protobuf.Empty) {
+ option (google.api.http) = {
+ post: "/api/v1/local/channel_pairs/{name}/modify"
+ body: "*"
+ };
+ }
+ // Delete a channel pair
+ rpc DeleteChannelpair(bbf_fiber.ChannelpairConfig) returns(google.protobuf.Empty) {
+ option (google.api.http) = {
+ delete: "/api/v1/local/channel_pairs/{name}/delete"
+ };
+ }
+ // List all channel terminations managed by this Voltha instance
+ rpc GetAllChannelterminationConfig(ID) returns(bbf_fiber.AllChannelterminationConfig) {
+ option (google.api.http) = {
+ get: "/api/v1/local/devices/{id}/channel_terminations"
+ };
+ }
+ // Create a channel termination
+ rpc CreateChanneltermination(bbf_fiber.ChannelterminationConfig) returns(google.protobuf.Empty) {
+ option (google.api.http) = {
+ post: "/api/v1/local/devices/{id}/channel_terminations/{name}"
+ body: "*"
+ };
+ }
+ // Update a channel termination
+ rpc UpdateChanneltermination(bbf_fiber.ChannelterminationConfig) returns(google.protobuf.Empty) {
+ option (google.api.http) = {
+ post: "/api/v1/local/devices/{id}/channel_terminations/{name}/modify"
+ body: "*"
+ };
+ }
+ // Delete a channel termination
+ rpc DeleteChanneltermination(bbf_fiber.ChannelterminationConfig) returns(google.protobuf.Empty) {
+ option (google.api.http) = {
+ delete: "/api/v1/local/devices/{id}/channel_terminations/{name}/delete"
+ };
+ }
+ // List all ont configs managed by this Voltha instance
+ rpc GetAllOntaniConfig(google.protobuf.Empty) returns(bbf_fiber.AllOntaniConfig) {
+ option (google.api.http) = {
+ get: "/api/v1/local/ont_anis"
+ };
+ }
+ // Create an ont configs
+ rpc CreateOntani(bbf_fiber.OntaniConfig) returns(google.protobuf.Empty) {
+ option (google.api.http) = {
+ post: "/api/v1/local/ont_anis/{name}"
+ body: "*"
+ };
+ }
+ // Update an ont configs
+ rpc UpdateOntani(bbf_fiber.OntaniConfig) returns(google.protobuf.Empty) {
+ option (google.api.http) = {
+ post: "/api/v1/local/ont_anis/{name}/modify"
+ body: "*"
+ };
+ }
+ // Delete an ont configs
+ rpc DeleteOntani(bbf_fiber.OntaniConfig) returns(google.protobuf.Empty) {
+ option (google.api.http) = {
+ delete: "/api/v1/local/ont_anis/{name}/delete"
+ };
+ }
+ // List all V ont configs managed by this Voltha instance
+ rpc GetAllVOntaniConfig(google.protobuf.Empty) returns(bbf_fiber.AllVOntaniConfig) {
+ option (google.api.http) = {
+ get: "/api/v1/local/v_ont_anis"
+ };
+ }
+ // Create a v ont configs
+ rpc CreateVOntani(bbf_fiber.VOntaniConfig) returns(google.protobuf.Empty) {
+ option (google.api.http) = {
+ post: "/api/v1/local/v_ont_anis/{name}"
+ body: "*"
+ };
+ }
+ // Update a v ont configs
+ rpc UpdateVOntani(bbf_fiber.VOntaniConfig) returns(google.protobuf.Empty) {
+ option (google.api.http) = {
+ post: "/api/v1/local/v_ont_anis/{name}/modify"
+ body: "*"
+ };
+ }
+ // Delete a v ont configs
+ rpc DeleteVOntani(bbf_fiber.VOntaniConfig) returns(google.protobuf.Empty) {
+ option (google.api.http) = {
+ delete: "/api/v1/local/v_ont_anis/{name}/delete"
+ };
+ }
+ // List all venet configs managed by this Voltha instance
+ rpc GetAllVEnetConfig(google.protobuf.Empty) returns(bbf_fiber.AllVEnetConfig) {
+ option (google.api.http) = {
+ get: "/api/v1/local/v_enets"
+ };
+ }
+ // Create venet configs
+ rpc CreateVEnet(bbf_fiber.VEnetConfig) returns(google.protobuf.Empty) {
+ option (google.api.http) = {
+ post: "/api/v1/local/v_enets/{name}"
+ body: "*"
+ };
+ }
+ // Update venet configs
+ rpc UpdateVEnet(bbf_fiber.VEnetConfig) returns(google.protobuf.Empty) {
+ option (google.api.http) = {
+ post: "/api/v1/local/v_enets/{name}/modify"
+ body: "*"
+ };
+ }
+ // Delete venet configs
+ rpc DeleteVEnet(bbf_fiber.VEnetConfig) returns(google.protobuf.Empty) {
+ option (google.api.http) = {
+ delete: "/api/v1/local/v_enets/{name}/delete"
+ };
+ }
// Stream control packets to the dataplane
rpc StreamPacketsOut(stream openflow_13.PacketOut)
returns(google.protobuf.Empty) {