VOL-2241:  Python 3 migration

 - rename adapter class file and remove unneeded __init__ to make imports work without major rearrange
 - venv and Dockerfile fixups needed for new pyvoltha (cannot install old first)
 - clean up yaml config file as it contained empty entries that failed to parse
 - clean up imports
 - remove itervalues iter*
 - convert to list() as needed
 - test with python 3.6
 - skip non-dict items in tcont loop
 - update to voltha-protos 2.1.0
 - migrate socketserver and simplehttpserver to python3 import

Change-Id: Id8efa72b6796a3055b1927716503a33544bb6548
diff --git a/python/Makefile b/python/Makefile
index 98005d2..c505319 100644
--- a/python/Makefile
+++ b/python/Makefile
@@ -96,9 +96,8 @@
 VENVDIR := venv-openonu
 
 venv: distclean local-protos local-pyvoltha
-	virtualenv ${VENVDIR};\
+	virtualenv --python=python3.6 ${VENVDIR};\
         source ./${VENVDIR}/bin/activate ; set -u ;\
-	rm ${VENVDIR}/local/bin ${VENVDIR}/local/lib ${VENVDIR}/local/include ;\
         pip install -r requirements.txt
 
 ifdef LOCAL_PYVOLTHA
diff --git a/python/__init__.py b/python/__init__.py
deleted file mode 100644
index cfcdc97..0000000
--- a/python/__init__.py
+++ /dev/null
@@ -1,15 +0,0 @@
-#
-# 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.
-#
\ No newline at end of file
diff --git a/python/adapters/__init__.py b/python/adapters/__init__.py
deleted file mode 100644
index 58aca1e..0000000
--- a/python/adapters/__init__.py
+++ /dev/null
@@ -1,13 +0,0 @@
-# Copyright 2018 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.
diff --git a/python/adapters/brcm_openomci_onu/__init__.py b/python/adapters/brcm_openomci_onu/__init__.py
deleted file mode 100644
index b0fb0b2..0000000
--- a/python/adapters/brcm_openomci_onu/__init__.py
+++ /dev/null
@@ -1,13 +0,0 @@
-# Copyright 2017-present Open Networking Foundation
-#
-# 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.
diff --git a/python/adapters/brcm_openomci_onu/brcm_openomci_onu.py b/python/adapters/brcm_openomci_onu/brcm_openomci_onu_adapter.py
similarity index 97%
rename from python/adapters/brcm_openomci_onu/brcm_openomci_onu.py
rename to python/adapters/brcm_openomci_onu/brcm_openomci_onu_adapter.py
index e44a072..5094cfc 100644
--- a/python/adapters/brcm_openomci_onu/brcm_openomci_onu.py
+++ b/python/adapters/brcm_openomci_onu/brcm_openomci_onu_adapter.py
@@ -20,22 +20,22 @@
 This adapter does NOT support XPON
 """
 
-from twisted.internet import reactor, task
+from __future__ import absolute_import
+import structlog
+from twisted.internet import reactor
 from twisted.internet.defer import inlineCallbacks
 
 from zope.interface import implementer
 
 from pyvoltha.adapters.interface import IAdapterInterface
-from pyvoltha.adapters.iadapter import OnuAdapter
 from voltha_protos.adapter_pb2 import Adapter
 from voltha_protos.adapter_pb2 import AdapterConfig
 from voltha_protos.common_pb2 import LogLevel
-from voltha_protos.device_pb2 import DeviceType, DeviceTypes, Port, Image
+from voltha_protos.device_pb2 import DeviceType, DeviceTypes
 from voltha_protos.health_pb2 import HealthStatus
 
 from pyvoltha.adapters.common.frameio.frameio import hexify
 from pyvoltha.adapters.extensions.omci.openomci_agent import OpenOMCIAgent, OpenOmciAgentDefaults
-from pyvoltha.adapters.extensions.omci.omci_me import *
 from pyvoltha.adapters.extensions.omci.database.mib_db_dict import MibDbVolatileDict
 
 from brcm_openomci_onu_handler import BrcmOpenomciOnuHandler
diff --git a/python/adapters/brcm_openomci_onu/brcm_openomci_onu_handler.py b/python/adapters/brcm_openomci_onu/brcm_openomci_onu_handler.py
index cd221a5..0cb381f 100644
--- a/python/adapters/brcm_openomci_onu/brcm_openomci_onu_handler.py
+++ b/python/adapters/brcm_openomci_onu/brcm_openomci_onu_handler.py
@@ -18,14 +18,16 @@
 Broadcom OpenOMCI OLT/ONU adapter handler.
 """
 
-import ast
+from __future__ import absolute_import
+import six
 import arrow
 import structlog
+import json
 
 from collections import OrderedDict
 
-from twisted.internet import reactor, task
-from twisted.internet.defer import DeferredQueue, inlineCallbacks, returnValue, TimeoutError
+from twisted.internet import reactor
+from twisted.internet.defer import DeferredQueue, inlineCallbacks
 
 from heartbeat import HeartBeat
 from pyvoltha.adapters.extensions.events.device_events.onu.onu_active_event import OnuActiveEvent
@@ -35,8 +37,10 @@
 
 import pyvoltha.common.openflow.utils as fd
 from pyvoltha.common.utils.registry import registry
+from pyvoltha.common.utils.nethelpers import mac_str_to_tuple
 from pyvoltha.common.config.config_backend import ConsulStore
 from pyvoltha.common.config.config_backend import EtcdStore
+from voltha_protos.logical_device_pb2 import LogicalPort
 from voltha_protos.common_pb2 import OperStatus, ConnectStatus, AdminState
 from voltha_protos.openflow_13_pb2 import OFPXMC_OPENFLOW_BASIC, ofp_port, OFPPS_LIVE, OFPPF_FIBER, OFPPF_1GB_FD
 from voltha_protos.inter_container_pb2 import InterAdapterMessageType, \
@@ -49,14 +53,15 @@
 from omci.brcm_tp_service_specific_task import BrcmTpServiceSpecificTask
 from omci.brcm_uni_lock_task import BrcmUniLockTask
 from omci.brcm_vlan_filter_task import BrcmVlanFilterTask
-from onu_gem_port import *
-from onu_tcont import *
-from pon_port import *
-from uni_port import *
-from onu_traffic_descriptor import *
+from onu_gem_port import OnuGemPort
+from onu_tcont import OnuTCont
+from pon_port import PonPort
+from uni_port import UniPort, UniType
+from onu_traffic_descriptor import OnuTrafficDescriptor
 from pyvoltha.common.tech_profile.tech_profile import TechProfile
 from pyvoltha.adapters.extensions.omci.tasks.omci_test_request import OmciTestRequest
 from pyvoltha.adapters.extensions.omci.omci_entities import AniG
+from pyvoltha.adapters.extensions.omci.omci_defs import EntityOperations, ReasonCodes
 
 OP = EntityOperations
 RC = ReasonCodes
@@ -154,10 +159,10 @@
 
     @property
     def uni_ports(self):
-        return self._unis.values()
+        return list(self._unis.values())
 
     def uni_port(self, port_no_or_name):
-        if isinstance(port_no_or_name, (str, unicode)):
+        if isinstance(port_no_or_name, six.string_types):
             return next((uni for uni in self.uni_ports
                          if uni.name == port_no_or_name), None)
 
@@ -448,8 +453,9 @@
                                    tp_path=tp_path)
                     return
 
-                tp = self.kv_client[tp_path]
-                tp = ast.literal_eval(tp)
+                tpstored = self.kv_client[tp_path]
+                tpstring = tpstored.decode('ascii')
+                tp = json.loads(tpstring)
                 self.log.debug("tp-instance", tp=tp)
                 self._do_tech_profile_configuration(uni_id, tp)
 
@@ -993,7 +999,7 @@
                     uni_entities[entity_id] = UniType.VEIP
 
                 uni_id = 0
-                for entity_id, uni_type in uni_entities.iteritems():
+                for entity_id, uni_type in uni_entities.items():
                     try:
                         yield self._add_uni_port(device, entity_id, uni_id, uni_type)
                         uni_id += 1
@@ -1074,7 +1080,7 @@
         self._unis[uni_port.port_number] = uni_port
 
         self._onu_omci_device.alarm_synchronizer.set_alarm_params(onu_id=self._onu_indication.onu_id,
-                                                                  uni_ports=self._unis.values(), serial_number=device.serial_number)
+                                                                  uni_ports=self.uni_ports, serial_number=device.serial_number)
 
     # TODO NEW CORE: Figure out how to gain this knowledge from the olt.  for now cheat terribly.
     def mk_uni_port_num(self, intf_id, onu_id, uni_id):
diff --git a/python/adapters/brcm_openomci_onu/heartbeat.py b/python/adapters/brcm_openomci_onu/heartbeat.py
index ffe4b69..386d0ab 100644
--- a/python/adapters/brcm_openomci_onu/heartbeat.py
+++ b/python/adapters/brcm_openomci_onu/heartbeat.py
@@ -12,6 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+from __future__ import absolute_import
 import structlog
 from twisted.internet import reactor
 from twisted.internet.defer import inlineCallbacks
diff --git a/python/adapters/brcm_openomci_onu/main.py b/python/adapters/brcm_openomci_onu/main.py
index 902ed0e..6e33571 100755
--- a/python/adapters/brcm_openomci_onu/main.py
+++ b/python/adapters/brcm_openomci_onu/main.py
@@ -17,13 +17,14 @@
 
 """OpenONU Adapter main entry point"""
 
+from __future__ import absolute_import
 import argparse
 import os
 import time
 
 import arrow
 import yaml
-import SocketServer
+import socketserver
 
 from packaging.version import Version
 from simplejson import dumps
@@ -46,10 +47,9 @@
 from pyvoltha.adapters.kafka.kafka_proxy import KafkaProxy, get_kafka_proxy
 from voltha_protos.adapter_pb2 import AdapterConfig
 
-from brcm_openomci_onu import BrcmOpenomciOnuAdapter
+from brcm_openomci_onu_adapter import BrcmOpenomciOnuAdapter
 from probe import Probe
 
-
 defs = dict(
     version_file='./VERSION',
     config=os.environ.get('CONFIG', './openonu.yml'),
@@ -299,9 +299,9 @@
         current_time = arrow.utcnow().timestamp
         self.instance_id = self.args.instance_id + '_' + str(current_time)
 
-        self.core_topic = args.core_topic
-        self.event_topic = args.event_topic
-        self.listening_topic = args.name
+        self.core_topic = str(args.core_topic)
+        self.event_topic = str(args.event_topic)
+        self.listening_topic = str(args.name)
         self.startup_components()
 
         if not args.no_heartbeat:
@@ -445,7 +445,7 @@
         args = self.args
         host = args.probe.split(':')[0]
         port = args.probe.split(':')[1]
-        server = SocketServer.TCPServer((host, int(port)), Probe)
+        server = socketserver.TCPServer((host, int(port)), Probe)
         server.serve_forever()
 
     @inlineCallbacks
@@ -509,14 +509,14 @@
                 else:
                     Probe.kafka_cluster_proxy_running = False
                     self.log.error('kafka-proxy-unavailable')
-            except Exception, e:
+            except Exception as e:
                 self.log.exception('failed-sending-message-heartbeat', e=e)
 
         try:
             t0 = time.time()
             lc = LoopingCall(send_msg, t0)
             lc.start(10)
-        except Exception, e:
+        except Exception as e:
             self.log.exception('failed-kafka-heartbeat', e=e)
 
 
diff --git a/python/adapters/brcm_openomci_onu/omci/brcm_capabilities_task.py b/python/adapters/brcm_openomci_onu/omci/brcm_capabilities_task.py
index d56a1d0..b6ca406 100644
--- a/python/adapters/brcm_openomci_onu/omci/brcm_capabilities_task.py
+++ b/python/adapters/brcm_openomci_onu/omci/brcm_capabilities_task.py
@@ -13,6 +13,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+from __future__ import absolute_import
 import structlog
 from pyvoltha.adapters.extensions.omci.tasks.onu_capabilities_task import OnuCapabilitiesTask
 from twisted.internet.defer import failure
diff --git a/python/adapters/brcm_openomci_onu/omci/brcm_mib_download_task.py b/python/adapters/brcm_openomci_onu/omci/brcm_mib_download_task.py
index 76af28b..f09379b 100644
--- a/python/adapters/brcm_openomci_onu/omci/brcm_mib_download_task.py
+++ b/python/adapters/brcm_openomci_onu/omci/brcm_mib_download_task.py
@@ -16,11 +16,13 @@
 import structlog
 from twisted.internet import reactor
 from twisted.internet.defer import inlineCallbacks, returnValue, TimeoutError, failure
-from pyvoltha.adapters.extensions.omci.omci_me import *
+from pyvoltha.adapters.extensions.omci.omci_me import PptpEthernetUniFrame, GalEthernetProfileFrame, \
+    MacBridgePortConfigurationDataFrame, MacBridgeServiceProfileFrame, Ieee8021pMapperServiceProfileFrame, \
+    VeipUniFrame, ExtendedVlanTaggingOperationConfigurationDataFrame
 from pyvoltha.adapters.extensions.omci.tasks.task import Task
-from pyvoltha.adapters.extensions.omci.omci_defs import *
-from adapters.brcm_openomci_onu.uni_port import *
-from adapters.brcm_openomci_onu.pon_port \
+from pyvoltha.adapters.extensions.omci.omci_defs import EntityOperations, ReasonCodes
+from uni_port import UniType
+from pon_port \
     import TASK_PRIORITY, DEFAULT_TPID, DEFAULT_GEM_PAYLOAD
 
 OP = EntityOperations
diff --git a/python/adapters/brcm_openomci_onu/omci/brcm_tp_service_specific_task.py b/python/adapters/brcm_openomci_onu/omci/brcm_tp_service_specific_task.py
index 7ba4523..62a1e51 100644
--- a/python/adapters/brcm_openomci_onu/omci/brcm_tp_service_specific_task.py
+++ b/python/adapters/brcm_openomci_onu/omci/brcm_tp_service_specific_task.py
@@ -13,15 +13,16 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+from __future__ import absolute_import
 import structlog
 from twisted.internet import reactor
-from twisted.internet.defer import inlineCallbacks, returnValue, TimeoutError, failure
-from pyvoltha.adapters.extensions.omci.omci_me import *
+from twisted.internet.defer import inlineCallbacks, TimeoutError, failure
+from pyvoltha.adapters.extensions.omci.omci_me import Ont2G, OmciNullPointer, PriorityQueueFrame, \
+    Ieee8021pMapperServiceProfileFrame
 from pyvoltha.adapters.extensions.omci.tasks.task import Task
-from pyvoltha.adapters.extensions.omci.omci_defs import *
-from pyvoltha.adapters.extensions.omci.omci_entities import *
-from adapters.brcm_openomci_onu.uni_port import *
-from adapters.brcm_openomci_onu.pon_port import TASK_PRIORITY, DEFAULT_GEM_PAYLOAD
+from pyvoltha.adapters.extensions.omci.omci_defs import EntityOperations, ReasonCodes
+from pyvoltha.adapters.extensions.omci.omci_entities import OntG, Tcont, PriorityQueueG
+from pon_port import TASK_PRIORITY
 
 
 OP = EntityOperations
@@ -90,12 +91,12 @@
         # due to additional tasks on different UNIs. So, it we cannot use the pon_port affter
         # this initializer
         self._tconts = []
-        for tcont in handler.pon_port.tconts.itervalues():
+        for tcont in list(handler.pon_port.tconts.values()):
             if tcont.uni_id is not None and tcont.uni_id != self._uni_port.uni_id: continue
             self._tconts.append(tcont)
 
         self._gem_ports = []
-        for gem_port in handler.pon_port.gem_ports.itervalues():
+        for gem_port in list(handler.pon_port.gem_ports.values()):
             if gem_port.uni_id is not None and gem_port.uni_id != self._uni_port.uni_id: continue
             self._gem_ports.append(gem_port)
 
@@ -189,6 +190,8 @@
                 if tcont.entity_id is None:
                     free_entity_id = None
                     for k, v in tcont_idents.items():
+                        if not isinstance(v, dict):
+                            continue
                         alloc_check = v.get('attributes', {}).get('alloc_id', 0)
                         # Some onu report both to indicate an available tcont
                         if alloc_check == 0xFF or alloc_check == 0xFFFF:
diff --git a/python/adapters/brcm_openomci_onu/omci/brcm_uni_lock_task.py b/python/adapters/brcm_openomci_onu/omci/brcm_uni_lock_task.py
index cbe22fa..aecefc1 100644
--- a/python/adapters/brcm_openomci_onu/omci/brcm_uni_lock_task.py
+++ b/python/adapters/brcm_openomci_onu/omci/brcm_uni_lock_task.py
@@ -13,6 +13,8 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 #
+
+from __future__ import absolute_import
 from pyvoltha.adapters.extensions.omci.tasks.task import Task
 from twisted.internet import reactor
 from twisted.internet.defer import inlineCallbacks, failure, returnValue
diff --git a/python/adapters/brcm_openomci_onu/omci/brcm_vlan_filter_task.py b/python/adapters/brcm_openomci_onu/omci/brcm_vlan_filter_task.py
index eaa3176..2589247 100644
--- a/python/adapters/brcm_openomci_onu/omci/brcm_vlan_filter_task.py
+++ b/python/adapters/brcm_openomci_onu/omci/brcm_vlan_filter_task.py
@@ -14,6 +14,7 @@
 # limitations under the License.
 #
 
+from __future__ import absolute_import
 import structlog
 from pyvoltha.adapters.extensions.omci.tasks.task import Task
 from twisted.internet import reactor
@@ -21,8 +22,8 @@
 from pyvoltha.adapters.extensions.omci.omci_defs import ReasonCodes, EntityOperations
 from pyvoltha.adapters.extensions.omci.omci_me import \
     VlanTaggingOperation, VlanTaggingFilterDataFrame, ExtendedVlanTaggingOperationConfigurationDataFrame
-from adapters.brcm_openomci_onu.uni_port import UniType
-from adapters.brcm_openomci_onu.pon_port import DEFAULT_TPID
+from uni_port import UniType
+from pon_port import DEFAULT_TPID
 
 RC = ReasonCodes
 OP = EntityOperations
diff --git a/python/adapters/brcm_openomci_onu/onu_gem_port.py b/python/adapters/brcm_openomci_onu/onu_gem_port.py
index 1ee28a6..baaa27d 100644
--- a/python/adapters/brcm_openomci_onu/onu_gem_port.py
+++ b/python/adapters/brcm_openomci_onu/onu_gem_port.py
@@ -13,10 +13,11 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+from __future__ import absolute_import
 import structlog
 from twisted.internet.defer import inlineCallbacks, returnValue
-from pyvoltha.adapters.extensions.omci.omci_me import *
-from pyvoltha.adapters.extensions.omci.omci_defs import *
+from pyvoltha.adapters.extensions.omci.omci_me import GemInterworkingTpFrame, GemPortNetworkCtpFrame
+from pyvoltha.adapters.extensions.omci.omci_defs import ReasonCodes
 
 RC = ReasonCodes
 
@@ -262,6 +263,7 @@
 
     @staticmethod
     def create(handler, gem_port):
+        log = structlog.get_logger(gem_port=gem_port)
         log.debug('function-entry', gem_port=gem_port)
 
         return OnuGemPort(gem_id=gem_port['gemport_id'],
diff --git a/python/adapters/brcm_openomci_onu/onu_tcont.py b/python/adapters/brcm_openomci_onu/onu_tcont.py
index aabaed8..80e98a0 100644
--- a/python/adapters/brcm_openomci_onu/onu_tcont.py
+++ b/python/adapters/brcm_openomci_onu/onu_tcont.py
@@ -13,10 +13,11 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+from __future__ import absolute_import
 import structlog
-from twisted.internet.defer import  inlineCallbacks, returnValue, succeed
-from pyvoltha.adapters.extensions.omci.omci_me import *
-from pyvoltha.adapters.extensions.omci.omci_defs import *
+from twisted.internet.defer import inlineCallbacks, returnValue
+from pyvoltha.adapters.extensions.omci.omci_me import TcontFrame
+from pyvoltha.adapters.extensions.omci.omci_defs import ReasonCodes
 
 RC = ReasonCodes
 
diff --git a/python/adapters/brcm_openomci_onu/onu_traffic_descriptor.py b/python/adapters/brcm_openomci_onu/onu_traffic_descriptor.py
index a70aa7e..1391e75 100644
--- a/python/adapters/brcm_openomci_onu/onu_traffic_descriptor.py
+++ b/python/adapters/brcm_openomci_onu/onu_traffic_descriptor.py
@@ -13,6 +13,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+from __future__ import absolute_import
 import structlog
 from twisted.internet.defer import inlineCallbacks, returnValue, succeed
 
diff --git a/python/adapters/brcm_openomci_onu/openonu.yml b/python/adapters/brcm_openomci_onu/openonu.yml
index 542fdf5..af7b003 100644
--- a/python/adapters/brcm_openomci_onu/openonu.yml
+++ b/python/adapters/brcm_openomci_onu/openonu.yml
@@ -36,13 +36,8 @@
             maxBytes: 2097152
             backupCount: 10
             level: DEBUG
-        null:
-            class: logging.NullHandler
 
     loggers:
-        amqp:
-            handlers: [null]
-            propagate: False
         conf:
             propagate: False
         '': # root logger
diff --git a/python/adapters/brcm_openomci_onu/pon_port.py b/python/adapters/brcm_openomci_onu/pon_port.py
index 5c8c7eb..5ed28b2 100644
--- a/python/adapters/brcm_openomci_onu/pon_port.py
+++ b/python/adapters/brcm_openomci_onu/pon_port.py
@@ -13,6 +13,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+from __future__ import absolute_import
 import structlog
 from twisted.internet.defer import inlineCallbacks, returnValue
 from voltha_protos.common_pb2 import AdminState, OperStatus
diff --git a/python/adapters/brcm_openomci_onu/probe.py b/python/adapters/brcm_openomci_onu/probe.py
index 6b4d39d..32646fd 100644
--- a/python/adapters/brcm_openomci_onu/probe.py
+++ b/python/adapters/brcm_openomci_onu/probe.py
@@ -13,7 +13,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 #
-from SimpleHTTPServer import SimpleHTTPRequestHandler
+from http.server import SimpleHTTPRequestHandler
 from structlog import get_logger
 
 log = get_logger()
diff --git a/python/adapters/brcm_openomci_onu/uni_port.py b/python/adapters/brcm_openomci_onu/uni_port.py
index 33fbf61..0548458 100644
--- a/python/adapters/brcm_openomci_onu/uni_port.py
+++ b/python/adapters/brcm_openomci_onu/uni_port.py
@@ -13,6 +13,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+from __future__ import absolute_import
 import structlog
 from enum import Enum
 from voltha_protos.common_pb2 import OperStatus, AdminState
diff --git a/python/docker/Dockerfile.openonu_adapter b/python/docker/Dockerfile.openonu_adapter
index 9c42a59..f21cc9f 100644
--- a/python/docker/Dockerfile.openonu_adapter
+++ b/python/docker/Dockerfile.openonu_adapter
@@ -11,26 +11,24 @@
 # 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 voltha/voltha-python-base:1.0.0
+FROM voltha/voltha-python-base:2.0.0
 
 # Install adapter requirements.
 COPY requirements.txt /tmp/requirements.txt
-RUN pip install -r /tmp/requirements.txt
+RUN pip install --no-cache-dir -r /tmp/requirements.txt
 
 ARG LOCAL_PYVOLTHA
 ARG LOCAL_PROTOS
 COPY local_imports/ /local_imports/
 RUN if [ -n "$LOCAL_PYVOLTHA" ] ; then \
-    pip install /local_imports/pyvoltha/dist/*.tar.gz ; \
+    pip install --no-cache-dir /local_imports/pyvoltha/dist/*.tar.gz ; \
 fi
 
 RUN if [ -n "$LOCAL_PROTOS" ] ; then \
-    pip install /local_imports/voltha-protos/dist/*.tar.gz ; \
+    pip install --no-cache-dir /local_imports/voltha-protos/dist/*.tar.gz ; \
 fi
 
 # Bundle app source
-RUN mkdir /voltha && touch /voltha/__init__.py
-RUN mkdir /voltha/adapters && touch /voltha/adapters/__init__.py
 ENV PYTHONPATH=/voltha
 COPY adapters/brcm_openomci_onu /voltha/adapters/brcm_openomci_onu
 
diff --git a/python/requirements.txt b/python/requirements.txt
index cee78b5..80f9ae0 100644
--- a/python/requirements.txt
+++ b/python/requirements.txt
@@ -1,2 +1,2 @@
-voltha-protos==1.0.0
-pyvoltha==2.2.5
+voltha-protos==2.1.0
+pyvoltha==2.3.0