VOL-2452: MIB Templating
- working for template and non-template cases
- works with resync
- convert binary string to ascii and strip out garbage, needed for json
- remove needless logging
- clearer mib dict get
- no need to swap equipment id, it assumed the same
- under load also need to increase kafka send/recv timeout
- if any omci element cannot be found allow normal upload to proceed
Change-Id: If42e4df812b5e4ab11e2dc81e075629099d556ff
diff --git a/VERSION b/VERSION
index bc4abe8..5aa7c52 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-2.3.8
+2.3.9
diff --git a/pyvoltha/adapters/extensions/omci/database/mib_db_dict.py b/pyvoltha/adapters/extensions/omci/database/mib_db_dict.py
index 92eaaec..e4066f6 100644
--- a/pyvoltha/adapters/extensions/omci/database/mib_db_dict.py
+++ b/pyvoltha/adapters/extensions/omci/database/mib_db_dict.py
@@ -301,6 +301,12 @@
elif isinstance(value, (list, dict)):
value = json.dumps(value, separators=(',', ':'))
+ if isinstance(value, six.string_types):
+ value = value.rstrip('\x00')
+
+ if isinstance(value, six.binary_type):
+ value = value.decode('ascii').rstrip('\x00')
+
assert db_value is None or isinstance(value, type(db_value)), \
"New value type for attribute '{}' type is changing from '{}' to '{}'".\
format(attribute, type(db_value), type(value))
@@ -467,19 +473,25 @@
def _fix_attr_json_attribute(self, attr_data, eca):
try:
- if eca is not None:
- field = eca.field
- if hasattr(field, 'load_json'):
- value = field.load_json(attr_data)
+ if eca is not None and hasattr(eca.field, 'load_json'):
+ try:
+ value = eca.field.load_json(attr_data)
return value
+ except ValueError:
+ pass
- return json.loads(attr_data) if isinstance(attr_data, six.string_types) else attr_data
+ if isinstance(attr_data, six.string_types):
+ try:
+ value = json.loads(attr_data)
+ return value
+ except ValueError:
+ pass
- except ValueError:
return attr_data
except Exception as e:
- pass
+ self.log.error('could-not-parse-attribute-returning-as-is', field=eca.field, attr_data=attr_data, e=e)
+ return attr_data
def update_supported_managed_entities(self, device_id, managed_entities):
"""
@@ -524,3 +536,31 @@
except Exception as e:
self.log.error('set-me-failure', e=e)
raise
+
+ def load_from_template(self, device_id, template):
+ now = datetime.utcnow()
+ headerdata = {
+ DEVICE_ID_KEY: device_id,
+ CREATED_KEY: now,
+ LAST_SYNC_KEY: None,
+ MDS_KEY: 0,
+ VERSION_KEY: MibDbVolatileDict.CURRENT_VERSION,
+ ME_KEY: dict(),
+ MSG_TYPE_KEY: set()
+ }
+ template.update(headerdata)
+ self._data[device_id] = template
+
+ def dump_to_json(self, device_id):
+ device_db = self._data.get(device_id, dict())
+ device_db = self._fix_dev_json_attributes(device_db, device_id)
+
+ def json_converter(o):
+ if isinstance(o, datetime):
+ return o.__str__()
+ if isinstance(o, six.binary_type):
+ return o.decode('ascii')
+
+ json_string = json.dumps(device_db, default=json_converter, indent=4)
+
+ return json_string
diff --git a/pyvoltha/adapters/extensions/omci/database/mib_template_db.py b/pyvoltha/adapters/extensions/omci/database/mib_template_db.py
new file mode 100644
index 0000000..a452c4f
--- /dev/null
+++ b/pyvoltha/adapters/extensions/omci/database/mib_template_db.py
@@ -0,0 +1,108 @@
+#
+# Copyright 2020 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 __future__ import absolute_import
+from .mib_db_api import CREATED_KEY, MODIFIED_KEY
+import json
+from datetime import datetime
+import structlog
+from pyvoltha.common.utils.registry import registry
+from pyvoltha.common.config.config_backend import EtcdStore
+import six
+
+
+class MibTemplateDb(object):
+
+ BASE_PATH = 'service/voltha/omci_mibs/templates'
+ TEMPLATE_PATH = '{}/{}/{}'
+
+ def __init__(self, vendor_id, equipment_id, software_version, serial_number, mac_address):
+ self.log = structlog.get_logger()
+ self._jsonstring = b''
+
+ # lookup keys
+ self._vendor_id = vendor_id
+ self._equipment_id = equipment_id
+ self._software_version = software_version
+
+ # replacement values
+ self._serial_number = serial_number
+ self._mac_address = mac_address
+
+ self.args = registry('main').get_args()
+ host, port = self.args.etcd.split(':', 1)
+ self._kv_store = EtcdStore(host, port, MibTemplateDb.BASE_PATH)
+ self.loaded = False
+ self._load_template()
+
+ def get_template_instance(self):
+ # swap out tokens with specific data
+ fixup = self._jsonstring.decode('ascii')
+ fixup = fixup.replace('%SERIAL_NUMBER%', self._serial_number)
+ fixup = fixup.replace('%MAC_ADDRESS%', self._mac_address)
+
+ # convert to a dict() compatible with mib_db_dict
+ newdb = self._load_from_json(fixup)
+ now = datetime.utcnow()
+
+ # populate timestamps as if it was mib uploaded
+ for cls_id, cls_data in newdb.items():
+ if isinstance(cls_id, int):
+ for inst_id, inst_data in cls_data.items():
+ if isinstance(inst_id, int):
+ newdb[cls_id][inst_id][CREATED_KEY] = now
+ newdb[cls_id][inst_id][MODIFIED_KEY] = now
+
+ return newdb
+
+ def _load_template(self):
+ path = self._get_template_path()
+ try:
+ self._jsonstring = self._kv_store[path]
+ self.log.debug('found-template-data', path=path)
+ self.loaded = True
+ except KeyError:
+ self.log.warn('no-template-found', path=path)
+
+ def _get_template_path(self):
+ if not isinstance(self._vendor_id, six.string_types):
+ raise TypeError('Vendor ID is a string')
+
+ if not isinstance(self._equipment_id, six.string_types):
+ raise TypeError('Equipment ID is a string')
+
+ if not isinstance(self._software_version, six.string_types):
+ raise TypeError('Software Version is a string')
+
+ fmt = MibTemplateDb.TEMPLATE_PATH
+ return fmt.format(self._vendor_id, self._equipment_id, self._software_version)
+
+ def _load_from_json(self, jsondata):
+
+ def json_obj_parser(x):
+ if isinstance(x, dict):
+ results = dict()
+ for (key, value) in x.items():
+ try:
+ key = int(key)
+ except (ValueError, TypeError):
+ pass
+
+ results.update({key: value})
+ return results
+ return x
+
+ template_data = json.loads(jsondata, object_hook=json_obj_parser)
+ return template_data
diff --git a/pyvoltha/adapters/extensions/omci/omci_cc.py b/pyvoltha/adapters/extensions/omci/omci_cc.py
index cc989a1..66c63b0 100644
--- a/pyvoltha/adapters/extensions/omci/omci_cc.py
+++ b/pyvoltha/adapters/extensions/omci/omci_cc.py
@@ -873,46 +873,26 @@
# MIB Action shortcuts
def send_mib_reset(self, timeout=DEFAULT_OMCI_TIMEOUT, high_priority=False):
- """
- Perform a MIB Reset
- """
- self.log.debug('send-mib-reset')
-
frame = OntDataFrame().mib_reset()
return self.send(frame, timeout=timeout, high_priority=high_priority)
def send_mib_upload(self, timeout=DEFAULT_OMCI_TIMEOUT, high_priority=False):
- self.log.debug('send-mib-upload')
-
frame = OntDataFrame().mib_upload()
return self.send(frame, timeout=timeout, high_priority=high_priority)
def send_mib_upload_next(self, seq_no, timeout=DEFAULT_OMCI_TIMEOUT, high_priority=False):
- self.log.debug('send-mib-upload-next')
-
frame = OntDataFrame(sequence_number=seq_no).mib_upload_next()
return self.send(frame, timeout=timeout, high_priority=high_priority)
def send_reboot(self, timeout=DEFAULT_OMCI_TIMEOUT, high_priority=False):
- """
- Send an ONU Device reboot request (ONU-G ME).
-
- NOTICE: This method is being deprecated and replaced with a tasks to preform this function
- """
- self.log.debug('send-mib-reboot')
-
frame = OntGFrame().reboot()
return self.send(frame, timeout=timeout, high_priority=high_priority)
def send_get_all_alarm(self, alarm_retrieval_mode=0, timeout=DEFAULT_OMCI_TIMEOUT, high_priority=False):
- self.log.debug('send_get_alarm')
-
frame = OntDataFrame().get_all_alarm(alarm_retrieval_mode)
return self.send(frame, timeout=timeout, high_priority=high_priority)
def send_get_all_alarm_next(self, seq_no, timeout=DEFAULT_OMCI_TIMEOUT, high_priority=False):
- self.log.debug('send_get_alarm_next')
-
frame = OntDataFrame().get_all_alarm_next(seq_no)
return self.send(frame, timeout=timeout, high_priority=high_priority)
@@ -921,27 +901,16 @@
return self.send(frame, timeout, 3, high_priority=high_priority)
def send_download_section(self, image_inst_id, section_num, data, size=DEFAULT_OMCI_DOWNLOAD_SECTION_SIZE, timeout=0, high_priority=False):
- """
- # timeout=0 indicates no repons needed
- """
- # self.log.debug("send_download_section", instance_id=image_inst_id, section=section_num, timeout=timeout)
+ # timeout=0 indicates no response needed
if timeout > 0:
frame = SoftwareImageFrame(image_inst_id).download_section(True, section_num, data)
else:
frame = SoftwareImageFrame(image_inst_id).download_section(False, section_num, data)
return self.send(frame, timeout, high_priority=high_priority)
- # if timeout > 0:
- # self.reactor.callLater(0, self.sim_receive_download_section_resp,
- # frame.fields["transaction_id"],
- # frame.fields["omci_message"].fields["section_number"])
- # return d
-
def send_end_software_download(self, image_inst_id, crc32, image_size, timeout=DEFAULT_OMCI_TIMEOUT, high_priority=False):
frame = SoftwareImageFrame(image_inst_id).end_software_download(crc32, image_size)
return self.send(frame, timeout, high_priority=high_priority)
- # self.reactor.callLater(0, self.sim_receive_end_software_download_resp, frame.fields["transaction_id"])
- # return d
def send_active_image(self, image_inst_id, flag=0, timeout=DEFAULT_OMCI_TIMEOUT, high_priority=False):
frame = SoftwareImageFrame(image_inst_id).activate_image(flag)
diff --git a/pyvoltha/adapters/extensions/omci/omci_me.py b/pyvoltha/adapters/extensions/omci/omci_me.py
index 1c12266..57412a1 100644
--- a/pyvoltha/adapters/extensions/omci/omci_me.py
+++ b/pyvoltha/adapters/extensions/omci/omci_me.py
@@ -569,12 +569,16 @@
"""
This managed entity models an executable software image stored in the ONU.
"""
- def __init__(self, entity_id):
+ def __init__(self, entity_id, attributes=None):
"""
:param entity_id: (int) This attribute uniquely identifies each instance of
this managed entity. (0..65535)
+ :param attributes: (basestring, list, set, dict) attributes. For gets
+ a string, list, or set can be provided. For create/set
+ operations, a dictionary should be provided, for
+ deletes None may be specified.
"""
- super(SoftwareImageFrame, self).__init__(SoftwareImage, entity_id, None)
+ super(SoftwareImageFrame, self).__init__(SoftwareImage, entity_id, MEFrame._attr_to_data(attributes))
class TcontFrame(MEFrame):
diff --git a/pyvoltha/adapters/extensions/omci/openomci_agent.py b/pyvoltha/adapters/extensions/omci/openomci_agent.py
index 5595816..0bf9d2b 100644
--- a/pyvoltha/adapters/extensions/omci/openomci_agent.py
+++ b/pyvoltha/adapters/extensions/omci/openomci_agent.py
@@ -20,6 +20,7 @@
from pyvoltha.adapters.extensions.omci.database.mib_db_ext import MibDbExternal
from pyvoltha.adapters.extensions.omci.state_machines.mib_sync import MibSynchronizer
from pyvoltha.adapters.extensions.omci.tasks.mib_upload import MibUploadTask
+from pyvoltha.adapters.extensions.omci.tasks.mib_template_task import MibTemplateTask
from pyvoltha.adapters.extensions.omci.tasks.get_mds_task import GetMdsTask
from pyvoltha.adapters.extensions.omci.tasks.mib_resync_task import MibResyncTask
from pyvoltha.adapters.extensions.omci.tasks.mib_reconcile_task import MibReconcileTask
@@ -48,6 +49,7 @@
'audit-delay': 60, # Time to wait between MIB audits. 0 to disable audits.
'tasks': {
'mib-upload': MibUploadTask,
+ 'mib-template': MibTemplateTask,
'get-mds': GetMdsTask,
'mib-audit': GetMdsTask,
'mib-resync': MibResyncTask,
diff --git a/pyvoltha/adapters/extensions/omci/state_machines/mib_sync.py b/pyvoltha/adapters/extensions/omci/state_machines/mib_sync.py
index f7f22fd..640da14 100644
--- a/pyvoltha/adapters/extensions/omci/state_machines/mib_sync.py
+++ b/pyvoltha/adapters/extensions/omci/state_machines/mib_sync.py
@@ -42,15 +42,17 @@
"""
OpenOMCI MIB Synchronizer state machine
"""
- DEFAULT_STATES = ['disabled', 'starting', 'uploading', 'examining_mds',
+ DEFAULT_STATES = ['disabled', 'starting', 'loading_mib_template', 'uploading', 'examining_mds',
'in_sync', 'out_of_sync', 'auditing', 'resynchronizing']
DEFAULT_TRANSITIONS = [
{'trigger': 'start', 'source': 'disabled', 'dest': 'starting'},
- {'trigger': 'upload_mib', 'source': 'starting', 'dest': 'uploading'},
+ {'trigger': 'load_mib_template', 'source': 'starting', 'dest': 'loading_mib_template'},
+ {'trigger': 'upload_mib', 'source': 'loading_mib_template', 'dest': 'uploading'},
{'trigger': 'examine_mds', 'source': 'starting', 'dest': 'examining_mds'},
+ {'trigger': 'success', 'source': 'loading_mib_template', 'dest': 'in_sync'},
{'trigger': 'success', 'source': 'uploading', 'dest': 'in_sync'},
{'trigger': 'success', 'source': 'examining_mds', 'dest': 'in_sync'},
@@ -122,6 +124,7 @@
self._resync_fail_limit = resync_fail_limit
self._upload_task = mib_sync_tasks['mib-upload']
+ self._load_mib_template_task = mib_sync_tasks['mib-template']
self._get_mds_task = mib_sync_tasks['get-mds']
self._audit_task = mib_sync_tasks['mib-audit']
self._resync_task = mib_sync_tasks['mib-resync']
@@ -366,13 +369,48 @@
if self.is_new_onu:
# clear resync failure counter if we "started over"
self._failed_resync_count = 0
- # Start full MIB upload
- self._deferred = reactor.callLater(0, self.upload_mib)
+ # Attempt to load a MIB template then start full MIB upload if needed
+ self._deferred = reactor.callLater(0, self.load_mib_template)
else:
# Examine the MIB Data Sync
self._deferred = reactor.callLater(0, self.examine_mds)
+ def on_enter_loading_mib_template(self):
+ """
+ Find and load a mib template. If not found proceed with mib_upload
+ """
+ self.advertise(OpenOmciEventType.state_change, self.state)
+
+ def success(template):
+ self.log.debug('mib-template-load-success')
+ self._current_task = None
+ self._next_resync = datetime.utcnow() + timedelta(seconds=self._resync_delay)
+
+ if template is not None:
+ self._database.load_from_template(self._device_id, template)
+
+ # DEBUG: Dump raw json db:
+ jsondb = self._database.dump_to_json(self.device_id)
+ self.log.debug('in-sync-device-db', json=jsondb)
+
+ self._deferred = reactor.callLater(0, self.success)
+ else:
+ # Start full MIB upload
+ self._deferred = reactor.callLater(0, self.upload_mib)
+
+ def failure(reason):
+ self.log.info('mib-template-load-failure', reason=reason)
+ self._current_task = None
+ self._deferred = reactor.callLater(self._timeout_delay, self.timeout)
+
+ self._device.mib_db_in_sync = False
+ self._current_task = self._load_mib_template_task(self._agent, self._device_id)
+
+ self.log.debug('starting-mib-template', task=self._current_task)
+ self._task_deferred = self._device.task_runner.queue_task(self._current_task)
+ self._task_deferred.addCallbacks(success, failure)
+
def on_enter_uploading(self):
"""
Begin full MIB data upload, starting with a MIB RESET
@@ -383,6 +421,11 @@
self.log.debug('mib-upload-success', results=results)
self._current_task = None
self._next_resync = datetime.utcnow() + timedelta(seconds=self._resync_delay)
+
+ # DEBUG: Dump raw json db:
+ jsondb = self._database.dump_to_json(self.device_id)
+ self.log.debug('in-sync-device-db', json=jsondb)
+
self._deferred = reactor.callLater(0, self.success)
def failure(reason):
@@ -393,6 +436,7 @@
self._device.mib_db_in_sync = False
self._current_task = self._upload_task(self._agent, self._device_id)
+ self.log.debug('starting-mib-upload', task=self._current_task)
self._task_deferred = self._device.task_runner.queue_task(self._current_task)
self._task_deferred.addCallbacks(success, failure)
@@ -589,7 +633,8 @@
response = msg[RX_RESPONSE_KEY]
# Check if expected in current mib_sync state
- if self.state != 'uploading' or self._omci_cc_subscriptions[RxEvent.MIB_Reset] is None:
+ if self.state not in ['uploading', 'loading_mib_template'] or \
+ self._omci_cc_subscriptions[RxEvent.MIB_Reset] is None:
self.log.error('rx-in-invalid-state', state=self.state)
else:
@@ -721,7 +766,7 @@
self.log.debug('on-create-response', state=self.state)
if self._omci_cc_subscriptions[RxEvent.Create]:
- if self.state in ['disabled', 'uploading']:
+ if self.state in ['disabled', 'uploading', 'loading_mib_template']:
self.log.error('rx-in-invalid-state', state=self.state)
return
try:
@@ -808,7 +853,7 @@
self.log.debug('on-delete-response', state=self.state)
if self._omci_cc_subscriptions[RxEvent.Delete]:
- if self.state in ['disabled', 'uploading']:
+ if self.state in ['disabled', 'uploading', 'loading_mib_template']:
self.log.error('rx-in-invalid-state', state=self.state)
return
try:
@@ -847,7 +892,7 @@
self.log.debug('on-set-response', state=self.state)
if self._omci_cc_subscriptions[RxEvent.Set]:
- if self.state in ['disabled', 'uploading']:
+ if self.state in ['disabled', 'uploading', 'loading_mib_template']:
self.log.error('rx-in-invalid-state', state=self.state)
return
try:
@@ -922,7 +967,7 @@
# All events for software run this method, checking for one is good enough
if self._omci_cc_subscriptions[RxEvent.Start_Software_Download]:
- if self.state in ['disabled', 'uploading']:
+ if self.state in ['disabled', 'uploading', 'loading_mib_template']:
self.log.error('rx-in-invalid-state', state=self.state)
return
try:
diff --git a/pyvoltha/adapters/extensions/omci/tasks/mib_template_task.py b/pyvoltha/adapters/extensions/omci/tasks/mib_template_task.py
new file mode 100644
index 0000000..505a444
--- /dev/null
+++ b/pyvoltha/adapters/extensions/omci/tasks/mib_template_task.py
@@ -0,0 +1,169 @@
+#
+# Copyright 2020 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 __future__ import absolute_import
+from .task import Task
+from twisted.internet.defer import inlineCallbacks, TimeoutError, failure, AlreadyCalledError, returnValue
+from twisted.internet import reactor
+from pyvoltha.adapters.extensions.omci.omci_defs import ReasonCodes
+from pyvoltha.adapters.extensions.omci.omci_me import OntGFrame, Ont2GFrame, SoftwareImageFrame, IpHostConfigDataFrame
+from pyvoltha.adapters.extensions.omci.database.mib_template_db import MibTemplateDb
+
+RC = ReasonCodes
+
+
+class MibTemplateTask(Task):
+ """
+ OpenOMCI MIB Template task
+
+ On successful completion, this task will call the 'callback' method of the
+ deferred returned by the start method. If successful either a new mib db
+ instance is returned or None, depending on if a template could be found.
+
+ Its expected if None is returned the caller will perform a full MIB upload
+
+ """
+ task_priority = 250
+ name = "MIB Template Task"
+
+ def __init__(self, omci_agent, device_id):
+ """
+ Class initialization
+
+ :param omci_agent: (OmciAdapterAgent) OMCI Adapter agent
+ :param device_id: (str) ONU Device ID
+ """
+ super(MibTemplateTask, self).__init__(MibTemplateTask.name,
+ omci_agent,
+ device_id,
+ priority=MibTemplateTask.task_priority)
+ self._device = omci_agent.get_device(device_id)
+ self._local_deferred = None
+
+ def cancel_deferred(self):
+ super(MibTemplateTask, self).cancel_deferred()
+
+ d, self._local_deferred = self._local_deferred, None
+ try:
+ if d is not None and not d.called:
+ d.cancel()
+ except:
+ pass
+
+ def start(self):
+ """
+ Start MIB Template tasks
+ """
+ super(MibTemplateTask, self).start()
+ self._local_deferred = reactor.callLater(0, self.create_template_instance)
+
+ def stop(self):
+ """
+ Shutdown MIB Template tasks
+ """
+ self.log.debug('stopping')
+
+ self.cancel_deferred()
+ super(MibTemplateTask, self).stop()
+
+ @inlineCallbacks
+ def create_template_instance(self):
+ """
+ Gather unique identifying elements from the ONU. Lookup template in persistent storage and return
+ If no template is found return None so normal MIB Upload sequence can happen
+ """
+ self.log.debug('create-mib-template-instance')
+
+ try:
+ # MIB Reset start fresh
+ self.strobe_watchdog()
+ results = yield self._device.omci_cc.send_mib_reset()
+
+ status = results.fields['omci_message'].fields['success_code']
+ if status != ReasonCodes.Success.value:
+ raise Exception('MIB Reset request failed with status code: {}'.format(status))
+
+ self.log.debug('gather-onu-info')
+
+ # Query for Vendor ID, Equipment ID and Software Version
+ results = yield self._get_omci(OntGFrame(attributes=['vendor_id', 'serial_number']))
+ self.log.debug('got-ontg', results=results)
+
+ vendor_id = results.get('vendor_id', b'').decode('ascii').rstrip('\x00')
+ serial_number = results.get('serial_number', '')
+
+ results = yield self._get_omci(Ont2GFrame(attributes='equipment_id'))
+ self.log.debug('got-ont2g', results=results)
+
+ equipment_id = results.get('equipment_id', b'').decode('ascii').rstrip('\x00')
+
+ # check only two software slots for active version.
+ results1 = yield self._get_omci(SoftwareImageFrame(0, attributes=['is_active', 'version']))
+ results2 = yield self._get_omci(SoftwareImageFrame(1, attributes=['is_active', 'version']))
+ self.log.debug('got-software', results1=results1, results2=results2)
+
+ software_version = ''
+ if results1.get('is_active') == 1:
+ software_version = results1.get('version', b'').decode('ascii').rstrip('\x00')
+ elif results2.get('is_active') == 1:
+ software_version = results2.get('version', b'').decode('ascii').rstrip('\x00')
+
+ results = yield self._get_omci(IpHostConfigDataFrame(1, attributes='mac_address'))
+ self.log.debug('got-ip-host-config', results=results)
+
+ mac_address = results.get('mac_address', '')
+
+ # Lookup template base on unique onu type info
+ template = None
+ if vendor_id and equipment_id and software_version:
+ self.log.debug('looking-up-template', vendor_id=vendor_id, equipment_id=equipment_id,
+ software_version=software_version)
+ template = MibTemplateDb(vendor_id, equipment_id, software_version, serial_number, mac_address)
+ else:
+ self.log.info('no-usable-template-lookup-data', vendor_id=vendor_id, equipment_id=equipment_id,
+ software_version=software_version)
+
+ if template and template.loaded:
+ # generate db instance
+ loaded_template_instance = template.get_template_instance()
+ self.deferred.callback(loaded_template_instance)
+ else:
+ self.deferred.callback(None)
+
+ except TimeoutError as e:
+ self.log.warn('mib-template-timeout', e=e)
+ self.deferred.errback(failure.Failure(e))
+
+ except AlreadyCalledError:
+ # Can occur if task canceled due to MIB Sync state change
+ self.log.debug('already-called-exception')
+ assert self.deferred.called, 'Unexpected AlreadyCalledError exception'
+ except Exception as e:
+ self.log.exception('mib-template', e=e)
+ self.deferred.errback(failure.Failure(e))
+
+ @inlineCallbacks
+ def _get_omci(self, frame):
+ self.strobe_watchdog()
+ results = yield self._device.omci_cc.send(frame.get())
+
+ results_fields = results.fields['omci_message'].fields
+ status = results_fields['success_code']
+
+ return_results = dict()
+ if status == RC.Success.value:
+ return_results = results_fields.get('data', dict())
+
+ returnValue(return_results)
diff --git a/pyvoltha/adapters/extensions/omci/tasks/mib_upload.py b/pyvoltha/adapters/extensions/omci/tasks/mib_upload.py
index d25acae..91c0a0d 100644
--- a/pyvoltha/adapters/extensions/omci/tasks/mib_upload.py
+++ b/pyvoltha/adapters/extensions/omci/tasks/mib_upload.py
@@ -95,18 +95,6 @@
try:
device = self.omci_agent.get_device(self.device_id)
- #########################################
- # MIB Reset
- self.strobe_watchdog()
- results = yield device.omci_cc.send_mib_reset()
-
- status = results.fields['omci_message'].fields['success_code']
- if status != ReasonCodes.Success.value:
- raise MibUploadFailure('MIB Reset request failed with status code: {}'.
- format(status))
-
- ########################################
- # Begin MIB Upload
self.strobe_watchdog()
results = yield device.omci_cc.send_mib_upload()
@@ -139,7 +127,7 @@
yield asleep(0.3)
# Successful if here
- self.log.info('mib-synchronized')
+ self.log.info('mib-uploaded')
self.deferred.callback('success, loaded {} ME Instances'.
format(number_of_commands))
diff --git a/pyvoltha/adapters/kafka/container_proxy.py b/pyvoltha/adapters/kafka/container_proxy.py
index 4e2fa12..578be3b 100644
--- a/pyvoltha/adapters/kafka/container_proxy.py
+++ b/pyvoltha/adapters/kafka/container_proxy.py
@@ -43,7 +43,7 @@
self.kafka_proxy = kafka_proxy
self.listening_topic = my_listening_topic
self.remote_topic = remote_topic
- self.default_timeout = 3
+ self.default_timeout = 6
def start(self):
log.info('started')
diff --git a/tox.ini b/tox.ini
index 7572850..d6f9451 100644
--- a/tox.ini
+++ b/tox.ini
@@ -13,7 +13,7 @@
; limitations under the License.
[tox]
-envlist = py27,py35,py36
+envlist = py35,py36
skip_missing_interpreters = true
[testenv]