ADTRAN: Update to containerized adapters.
Loading and running but still needs about a week or so of work to
catch up to where the OpenOLT/ONU containerized adapters are
Change-Id: I5522232e21dd76b3f95b4698af6c7e4cef96753d
diff --git a/.gitignore b/.gitignore
index 13af726..5733c21 100644
--- a/.gitignore
+++ b/.gitignore
@@ -179,3 +179,10 @@
# Output of the go coverage tool, specifically when used with LiteIDE
*.out
+#################
+# Other
+docs/
+/venv-linux/
+/voltha-protos/
+/bin/
+/.idea/
\ No newline at end of file
diff --git a/Makefile b/Makefile
index 6833f4b..6cec29c 100644
--- a/Makefile
+++ b/Makefile
@@ -43,18 +43,19 @@
--rm --force-rm \
$(DOCKER_BUILD_EXTRA_ARGS)
-VENVDIR := venv-$(shell uname -s | tr '[:upper:]' '[:lower:]')
-VENV_BIN ?= virtualenv
-VENV_OPTS ?=
-
-PYVOLTHA_DIR ?= ../pyvoltha
-
DOCKER_IMAGE_LIST = \
voltha-adtran-base \
- voltha-adapter-adtran-onu \
voltha-adapter-adtran-olt
+ # voltha-adapter-adtran-onu \
-.PHONY: base adtran_olt adtran_onu tag push pull
+VENVDIR := venv-$(shell uname -s | tr '[:upper:]' '[:lower:]')
+VENV_BIN ?= virtualenv
+VENV_OPTS ?= -v
+
+PYVOLTHA_DIR ?= ../pyvoltha
+VOLTHA_PROTO_DIR ?= ../voltha-protos
+
+.PHONY: $(DIRS) $(DIRS_CLEAN) base adtran_olt adtran_onu tag push pull
# This should to be the first and default target in this Makefile
help:
@@ -65,9 +66,8 @@
If this is the first time you are building, choose \"make build\" option."
@echo "clean : Remove files created by the build and tests"
@echo "distclean : Remove venv directory"
- @echo "fetch : Pre-fetch artifacts for subsequent local builds"
@echo "help : Print this help"
- @echo "rebuild-venv : Rebuild local Python virtualenv from scratch"
+ @echo "rebuild-venv : Rebuild local Pythozn virtualenv from scratch"
@echo "venv : Build local Python virtualenv if did not exist yet"
@echo "containers : Build all the docker containers"
@echo "base : Build the base docker container used by all other dockers"
@@ -80,13 +80,17 @@
build: containers
-containers: base adapter_adtran_olt adapter_adtran_onu
+# containers: base adapter_adtran_olt adapter_adtran_onu olt_only onu_only
+containers: base adapter_adtran_olt olt_only
base:
ifdef LOCAL_PYVOLTHA
@rm -f pyvoltha/dist/*
@mkdir -p pyvoltha/dist
cp $(PYVOLTHA_DIR)/dist/*.tar.gz pyvoltha/dist/
+ @rm -f voltha-protos/*
+ mkdir -p voltha-protos/dist
+ cp $(VOLTHA_PROTO_DIR)/dist/*.tar.gz voltha-protos/dist/
docker build $(DOCKER_BUILD_ARGS) -t ${REGISTRY}${REPOSITORY}voltha-adtran-base-local:${TAG} -f docker/Dockerfile.base_local .
else
docker build $(DOCKER_BUILD_ARGS) -t ${REGISTRY}${REPOSITORY}voltha-adtran-base:${TAG} -f docker/Dockerfile.base .
@@ -106,6 +110,20 @@
docker build $(DOCKER_BUILD_ARGS) -t ${REGISTRY}${REPOSITORY}voltha-adapter-adtran-onu:${TAG} -f docker/Dockerfile.adapter_adtran_onu .
endif
+olt_only: base
+ifdef PYVOLTHA_BASE_IMAGE
+ docker build $(DOCKER_BUILD_ARGS) -t ${REGISTRY}${REPOSITORY}voltha-adapter-adtran-olt:${TAG} -f docker/Dockerfile.adapter_adtran_olt_pyvoltha .
+else
+ docker build $(DOCKER_BUILD_ARGS) -t ${REGISTRY}${REPOSITORY}voltha-adapter-adtran-olt:${TAG} -f docker/Dockerfile.adapter_adtran_olt .
+endif
+
+onu_only:
+ifdef PYVOLTHA_BASE_IMAGE
+ docker build $(DOCKER_BUILD_ARGS) -t ${REGISTRY}${REPOSITORY}voltha-adapter-adtran-onu:${TAG} -f docker/Dockerfile.adapter_adtran_onu_pyvoltha .
+else
+ docker build $(DOCKER_BUILD_ARGS) -t ${REGISTRY}${REPOSITORY}voltha-adapter-adtran-onu:${TAG} -f docker/Dockerfile.adapter_adtran_onu .
+endif
+
tag: $(patsubst %,%.tag,$(DOCKER_IMAGE_LIST))
push: tag $(patsubst %,%.push,$(DOCKER_IMAGE_LIST))
@@ -122,8 +140,9 @@
docker pull ${REGISTRY}${REPOSITORY}voltha-$(subst .pull,,$@):${TAG}
clean:
- find . -name '*.pyc' | xargs rm -f
rm -rf pyvoltha
+ rm -rf voltha-protos
+ find . -name '*.pyc' | xargs rm -f
distclean: clean
rm -rf ${VENVDIR}
@@ -151,9 +170,12 @@
ifdef LOCAL_PYVOLTHA
mkdir -p pyvoltha/dist
- cp ../../pyvoltha/dist/*.tar.gz pyvoltha/dist/
+ cp $(PYVOLTHA_DIR)/dist/*.tar.gz pyvoltha/dist/
+ mkdir -p voltha-protos/dist
+ cp $(VOLTHA_PROTO_DIR)/dist/*.tar.gz voltha-protos/dist/
@ . ${VENVDIR}/bin/activate && \
- pip install pyvoltha/dist/*.tar.gz
+ pip install pyvoltha/dist/*.tar.gz && \
+ pip install voltha-protos/dist/*.tar.gz
endif
# end file
diff --git a/adapters/adtran_common/adtran_device_handler.py b/adapters/adtran_common/adtran_device_handler.py
index 79877b7..308cc0b 100644
--- a/adapters/adtran_common/adtran_device_handler.py
+++ b/adapters/adtran_common/adtran_device_handler.py
@@ -35,6 +35,8 @@
from pyvoltha.adapters.extensions.kpi.olt.olt_pm_metrics import OltPmMetrics
from pyvoltha.common.utils.asleep import asleep
from flow.flow_tables import DeviceFlows, DownstreamFlows
+from adapters.adtran_olt.net.pio_zmq import DEFAULT_PIO_TCP_PORT
+from adapters.adtran_olt.net.pon_zmq import DEFAULT_PON_AGENT_TCP_PORT
_ = third_party
@@ -86,8 +88,6 @@
RESTART_RPC = '<system-restart xmlns="urn:ietf:params:xml:ns:yang:ietf-system"/>'
def __init__(self, **kwargs):
- from net.pio_zmq import DEFAULT_PIO_TCP_PORT
- from net.pon_zmq import DEFAULT_PON_AGENT_TCP_PORT
super(AdtranDeviceHandler, self).__init__()
@@ -159,9 +159,6 @@
self.heartbeat = None
self.heartbeat_last_reason = ''
- # Virtualized OLT Support
- self.is_virtual_olt = False
-
# Installed flows
self._evcs = {} # Flow ID/name -> FlowEntry
@@ -233,7 +230,7 @@
self.host_and_port = device.host_and_port.split(":")
self.ip_address = self.host_and_port[0]
self.netconf_port = int(self.host_and_port[1])
- self.adapter_agent.update_device(device)
+ self.adapter_agent.device_update(device)
else:
self.activate_failed(device, 'No IP_address field provided')
@@ -335,14 +332,10 @@
self.parse_provisioning_options(device)
############################################################################
- # Currently, only virtual OLT (pizzabox) is supported
- # self.is_virtual_olt = Add test for MOCK Device if we want to support it
-
- ############################################################################
# Start initial discovery of NETCONF support (if any)
try:
device.reason = 'establishing NETCONF connection'
- self.adapter_agent.update_device(device)
+ yield self.adapter_agent.device_update(device)
self.startup = self.make_netconf_connection()
yield self.startup
@@ -355,7 +348,7 @@
# Update access information on network device for full protocol support
try:
device.reason = 'device networking validation'
- self.adapter_agent.update_device(device)
+ yield self.adapter_agent.device_update(device)
self.startup = self.ready_network_access()
yield self.startup
@@ -367,7 +360,7 @@
# Restconf setup
try:
device.reason = 'establishing RESTConf connections'
- self.adapter_agent.update_device(device)
+ yield self.adapter_agent.device_update(device)
self.startup = self.make_restconf_connection()
yield self.startup
@@ -379,11 +372,11 @@
# Get the device Information
if reconciling:
device.connect_status = ConnectStatus.REACHABLE
- self.adapter_agent.update_device(device)
+ yield self.adapter_agent.device_update(device)
else:
try:
device.reason = 'retrieving device information'
- self.adapter_agent.update_device(device)
+ yield self.adapter_agent.device_update(device)
self.startup = self.get_device_info(device)
results = yield self.startup
@@ -396,7 +389,7 @@
device.root = True
device.vendor = results.get('vendor', 'Adtran Inc.')
device.connect_status = ConnectStatus.REACHABLE
- self.adapter_agent.update_device(device)
+ yield self.adapter_agent.device_update(device)
except Exception as e:
self.log.exception('device-info', e=e)
@@ -405,7 +398,7 @@
try:
# Enumerate and create Northbound NNI interfaces
device.reason = 'enumerating northbound interfaces'
- self.adapter_agent.update_device(device)
+ yield self.adapter_agent.device_update(device)
self.startup = self.enumerate_northbound_ports(device)
results = yield self.startup
@@ -413,7 +406,7 @@
yield self.startup
device.reason = 'adding northbound interfaces to adapter'
- self.adapter_agent.update_device(device)
+ yield self.adapter_agent.device_update(device)
if not reconciling:
for port in self.northbound_ports.itervalues():
@@ -426,7 +419,7 @@
try:
# Enumerate and create southbound interfaces
device.reason = 'enumerating southbound interfaces'
- self.adapter_agent.update_device(device)
+ yield self.adapter_agent.device_update(device)
self.startup = self.enumerate_southbound_ports(device)
results = yield self.startup
@@ -434,7 +427,7 @@
yield self.startup
device.reason = 'adding southbound interfaces to adapter'
- self.adapter_agent.update_device(device)
+ yield self.adapter_agent.device_update(device)
if not reconciling:
for port in self.southbound_ports.itervalues():
@@ -471,7 +464,7 @@
if self.pm_metrics is None:
try:
device.reason = 'setting up Performance Monitoring configuration'
- self.adapter_agent.update_device(device)
+ yield self.adapter_agent.device_update(device)
kwargs = {
'nni-ports': self.northbound_ports.values(),
@@ -483,7 +476,7 @@
pm_config = self.pm_metrics.make_proto()
self.log.debug("initial-pm-config", pm_config=pm_config)
- self.adapter_agent.update_device_pm_config(pm_config, init=True)
+ yield self.adapter_agent.device_pm_config_update(pm_config, init=True)
except Exception as e:
self.log.exception('pm-setup', e=e)
@@ -493,7 +486,7 @@
# Set the ports in a known good initial state
if not reconciling:
device.reason = 'setting device to a known initial state'
- self.adapter_agent.update_device(device)
+ yield self.adapter_agent.device_update(device)
try:
for port in self.northbound_ports.itervalues():
self.startup = yield port.reset()
@@ -509,7 +502,7 @@
# Create logical ports for all southbound and northbound interfaces
try:
device.reason = 'creating logical ports'
- self.adapter_agent.update_device(device)
+ yield self.adapter_agent.device_update(device)
self.startup = self.create_logical_ports(device, ld_initialized, reconciling)
yield self.startup
@@ -520,7 +513,7 @@
############################################################################
# Setup Alarm handler
device.reason = 'setting up adapter alarms'
- self.adapter_agent.update_device(device)
+ yield self.adapter_agent.device_update(device)
self.alarms = AdapterAlarms(self.adapter_agent, device.id, ld_initialized.id)
@@ -531,7 +524,7 @@
try:
self.log.debug('device-activation-procedures')
device.reason = 'performing model specific activation procedures'
- self.adapter_agent.update_device(device)
+ yield self.adapter_agent.device_update(device)
self.startup = self.complete_device_specific_activation(device, reconciling)
yield self.startup
@@ -547,7 +540,7 @@
device.parent_id = ld_initialized.id
device.oper_status = OperStatus.ACTIVE
device.reason = ''
- self.adapter_agent.update_device(device)
+ yield self.adapter_agent.device_update(device)
self.logical_device_id = ld_initialized.id
# Start collecting stats from the device after a brief pause
@@ -567,6 +560,7 @@
returnValue('activated')
+ @inlineCallbacks
def restart_activate(self, done_deferred, reconciling):
"""
Startup activation failed, pause a short period of time and retry
@@ -580,18 +574,20 @@
d.cancel()
except:
pass
+
device = self.adapter_agent.get_device(self.device_id)
device.reason = 'Failed during {}, retrying'.format(device.reason)
- self.adapter_agent.update_device(device)
+ yield self.adapter_agent.device_update(device)
self.startup = reactor.callLater(_STARTUP_RETRY_TIMEOUT, self.activate,
done_deferred, reconciling)
- return 'retrying'
+ returnValue('retrying')
@inlineCallbacks
def ready_network_access(self):
# Override in device specific class if needed
returnValue('nop')
+ @inlineCallbacks
def activate_failed(self, device, reason, reachable=True):
"""
Activation process (adopt_device) has failed.
@@ -608,7 +604,7 @@
device.connect_status = ConnectStatus.UNREACHABLE
device.reason = reason
- self.adapter_agent.update_device(device)
+ yield self.adapter_agent.device_update(device)
raise Exception('Failed to activate OLT: {}'.format(device.reason))
@inlineCallbacks
@@ -625,19 +621,11 @@
client = self._netconf_client
if client is None:
- if not self.is_virtual_olt:
- client = AdtranNetconfClient(self.ip_address,
- self.netconf_port,
- self.netconf_username,
- self.netconf_password,
- self.timeout)
- else:
- from python.adapters.adtran.adtran_common.net.mock_netconf_client import MockNetconfClient
- client = MockNetconfClient(self.ip_address,
- self.netconf_port,
- self.netconf_username,
- self.netconf_password,
- self.timeout)
+ client = AdtranNetconfClient(self.ip_address,
+ self.netconf_port,
+ self.netconf_username,
+ self.netconf_password,
+ self.timeout)
if client.connected:
self._netconf_client = client
returnValue(True)
@@ -889,7 +877,7 @@
# Get the latest device reference
device = self.adapter_agent.get_device(self.device_id)
device.reason = 'Disabling'
- self.adapter_agent.update_device(device)
+ yield self.adapter_agent.device_update(device)
# Drop registration for ONU detection
# self.adapter_agent.unregister_for_onu_detect_state(self.device.id)
@@ -905,7 +893,7 @@
device.oper_status = OperStatus.UNKNOWN
device.connect_status = ConnectStatus.UNREACHABLE
- self.adapter_agent.update_device(device)
+ yield self.adapter_agent.device_update(device)
# Disable all child devices first
self.adapter_agent.update_child_devices_state(self.device_id,
@@ -941,7 +929,7 @@
self._rest_client = None
device.reason = ''
- self.adapter_agent.update_device(device)
+ yield self.adapter_agent.device_update(device)
self.log.info('disabled', device_id=device.id)
returnValue(None)
@@ -972,7 +960,7 @@
# Update the connect status to REACHABLE
device.connect_status = ConnectStatus.REACHABLE
device.oper_status = OperStatus.ACTIVATING
- self.adapter_agent.update_device(device)
+ yield self.adapter_agent.device_update(device)
# Reenable any previously configured southbound ports
for port in self.southbound_ports.itervalues():
@@ -1015,7 +1003,7 @@
self.logical_device_id = ld_initialized.id
# update device active status now
- self.adapter_agent.update_device(device)
+ yield self.adapter_agent.device_update(device)
# Reenable all child devices
self.adapter_agent.update_child_devices_state(device.id,
@@ -1051,14 +1039,12 @@
except:
pass
# Issue reboot command
+ try:
+ yield self.netconf_client.rpc(AdtranDeviceHandler.RESTART_RPC)
- if not self.is_virtual_olt:
- try:
- yield self.netconf_client.rpc(AdtranDeviceHandler.RESTART_RPC)
-
- except Exception as e:
- self.log.exception('NETCONF-shutdown', e=e)
- returnValue(defer.fail(Failure()))
+ except Exception as e:
+ self.log.exception('NETCONF-shutdown', e=e)
+ returnValue(defer.fail(Failure()))
# self.adapter_agent.unregister_for_onu_detect_state(self.device.id)
@@ -1070,7 +1056,7 @@
previous_conn_status = device.connect_status
device.oper_status = OperStatus.ACTIVATING
device.connect_status = ConnectStatus.UNREACHABLE
- self.adapter_agent.update_device(device)
+ yield self.adapter_agent.device_update(device)
# Update the child devices connect state to UNREACHABLE
self.adapter_agent.update_child_devices_state(self.device_id,
@@ -1130,7 +1116,7 @@
finally:
self._netconf_client = None
- if (self.netconf_client is None and not self.is_virtual_olt) or self.rest_client is None:
+ if self.netconf_client is None or self.rest_client is None:
current_time = time.time()
if current_time < timeout:
self.startup = reactor.callLater(5, self._finish_reboot, timeout,
@@ -1138,7 +1124,7 @@
previous_conn_status)
returnValue(self.startup)
- if self.netconf_client is None and not self.is_virtual_olt:
+ if self.netconf_client is None:
self.log.error('NETCONF-restore-failure')
pass # TODO: What is best course of action if cannot get clients back?
@@ -1154,7 +1140,7 @@
device = self.adapter_agent.get_device(self.device_id)
device.oper_status = previous_oper_status
device.connect_status = previous_conn_status
- self.adapter_agent.update_device(device)
+ yield self.adapter_agent.device_update(device)
# Update the child devices connect state to REACHABLE
self.adapter_agent.update_child_devices_state(self.device_id,
@@ -1216,7 +1202,7 @@
# Get the latest device reference
device = self.adapter_agent.get_device(self.device_id)
device.reason = 'Deleting'
- self.adapter_agent.update_device(device)
+ yield self.adapter_agent.device_update(device)
# self.adapter_agent.unregister_for_onu_detect_state(self.device.id)
@@ -1327,6 +1313,7 @@
if active and self.netconf_client is None or not self.netconf_client.connected:
self.make_netconf_connection(close_existing_client=True)
+ @inlineCallbacks
def heartbeat_check_status(self, _):
"""
Check the number of heartbeat failures against the limit and emit an alarm if needed
@@ -1342,7 +1329,7 @@
device.connect_status = ConnectStatus.UNREACHABLE
device.oper_status = OperStatus.FAILED
device.reason = self.heartbeat_last_reason
- self.adapter_agent.update_device(device)
+ yield self.adapter_agent.device_update(device)
HeartbeatAlarm(self.alarms, 'olt', self.heartbeat_miss).raise_alarm()
self.on_heatbeat_alarm(True)
else:
@@ -1351,7 +1338,7 @@
device.connect_status = ConnectStatus.REACHABLE
device.oper_status = OperStatus.ACTIVE
device.reason = ''
- self.adapter_agent.update_device(device)
+ yield self.adapter_agent.device_update(device)
HeartbeatAlarm(self.alarms, 'olt').clear_alarm()
self.on_heatbeat_alarm(False)
diff --git a/adapters/adtran_olt/adtran_olt.yml b/adapters/adtran_olt/adapters-adtran-olt.yml
similarity index 100%
rename from adapters/adtran_olt/adtran_olt.yml
rename to adapters/adtran_olt/adapters-adtran-olt.yml
diff --git a/adapters/adtran_olt/adtran_olt.py b/adapters/adtran_olt/adtran_olt.py
index c052b78..e25b42a 100644
--- a/adapters/adtran_olt/adtran_olt.py
+++ b/adapters/adtran_olt/adtran_olt.py
@@ -22,7 +22,7 @@
from pyvoltha.adapters.iadapter import OltAdapter
from pyvoltha.protos import third_party
from pyvoltha.protos.common_pb2 import AdminState
-
+from pyvoltha.protos.health_pb2 import HealthStatus
from adtran_olt_handler import AdtranOltHandler
@@ -43,7 +43,7 @@
version='2.0.0',
device_type=AdtranOltAdapter.name,
accepts_bulk_flow_update=True,
- accepts_add_remove_flow_updates=False) # TODO: Implement me
+ accepts_add_remove_flow_updates=True)
log.debug('adtran_olt.__init__')
@@ -55,7 +55,6 @@
"""
# TODO: Currently this is always healthy for every adapter.
# If we decide not to modify this, delete this method and use base class method
- from pyvoltha.protos.health_pb2 import HealthStatus
return HealthStatus(state=HealthStatus.HEALTHY)
def abandon_device(self, device):
@@ -75,8 +74,9 @@
is provisioned top-down and needs to be activated by the adapter.
:param device: A voltha.Device object, with possible device-type
- specific extensions. Such extensions shall be described as part of
- the device type specification returned by device_types().
+ specific extensions. Such extensions shall be described as part of
+ the device type specification returned by device_types().
+
:return: (Deferred) Shall be fired to acknowledge device ownership.
"""
log.info('adopt-device', device=device)
@@ -84,23 +84,36 @@
'adapter': self,
'device-id': device.id
}
- self.devices_handlers[device.id] = self.device_handler_class(**kwargs)
- d = defer.Deferred()
- reactor.callLater(0, self.devices_handlers[device.id].activate, d, False)
- return d
+ try:
+ self.devices_handlers[device.id] = self.device_handler_class(**kwargs)
+ d = defer.Deferred()
+ reactor.callLater(0, self.devices_handlers[device.id].activate, d, False)
+ return d
+
+ except Exception as _e:
+ raise
def reconcile_device(self, device):
+ """
+ Make sure the adapter looks after given device. Called when this
+ device has changed ownership from another Voltha instance to
+ this one (typically, this occurs when the previous voltha
+ instance went down).
+
+ :param device: A voltha.Device object, with possible device-type
+ specific extensions. Such extensions shall be described as part of
+ the device type specification returned by device_types().
+
+ :return: (Deferred) Shall be fired to acknowledge device ownership.
+ """
try:
- self.devices_handlers[device.id] = self.device_handler_class(self,
- device.id)
+ kwargs = {
+ 'adapter': self,
+ 'device-id': device.id
+ }
+ self.devices_handlers[device.id] = self.device_handler_class(**kwargs)
# Work only required for devices that are in ENABLED state
if device.admin_state == AdminState.ENABLED:
-
- kwargs = {
- 'adapter': self,
- 'device-id': device.id
- }
- self.devices_handlers[device.id] =self.device_handler_class(**kwargs)
d = defer.Deferred()
reactor.callLater(0, self.devices_handlers[device.id].activate, d, True)
diff --git a/adapters/adtran_olt/adtran_olt_handler.py b/adapters/adtran_olt/adtran_olt_handler.py
index ad32b84..92c3398 100644
--- a/adapters/adtran_olt/adtran_olt_handler.py
+++ b/adapters/adtran_olt/adtran_olt_handler.py
@@ -160,9 +160,6 @@
'startup-revision': 'unknown',
'software-images': []
}
- if self.is_virtual_olt:
- returnValue(device)
-
try:
pe_state = PhysicalEntitiesState(self.netconf_client)
self.startup = pe_state.get_state()
@@ -322,12 +319,8 @@
from nni_port import MockNniPort
ietf_interfaces = IetfInterfacesState(self.netconf_client)
-
- if self.is_virtual_olt:
- results = MockNniPort.get_nni_port_state_results()
- else:
- self.startup = ietf_interfaces.get_state()
- results = yield self.startup
+ self.startup = ietf_interfaces.get_state()
+ results = yield self.startup
ports = ietf_interfaces.get_port_entries(results, 'ethernet')
returnValue(ports)
@@ -355,10 +348,9 @@
# May already exist if device was not fully reachable when first enabled
if port_no not in self.northbound_ports:
self.log.info('processing-nni', port_no=port_no, name=port['port_no'])
- self.northbound_ports[port_no] = NniPort(self, **port) if not self.is_virtual_olt \
- else MockNniPort(self, **port)
+ self.northbound_ports[port_no] = NniPort(self, **port)
- if len(self.northbound_ports) >= self.max_nni_ports: # TODO: For now, limit number of NNI ports to make debugging easier
+ if len(self.northbound_ports) >= self.max_nni_ports: # TODO: For now, limit number of NNI ports to make debugging easier
break
self.num_northbound_ports = len(self.northbound_ports)
@@ -407,12 +399,8 @@
results = yield self.startup
ietf_interfaces = IetfInterfacesState(self.netconf_client)
-
- if self.is_virtual_olt:
- nc_results = MockNniPort.get_pon_port_state_results()
- else:
- self.startup = ietf_interfaces.get_state()
- nc_results = yield self.startup
+ self.startup = ietf_interfaces.get_state()
+ nc_results = yield self.startup
ports = ietf_interfaces.get_port_entries(nc_results, 'xpon')
if len(ports) == 0:
@@ -692,7 +680,7 @@
# Upstream direction?
if self.is_pon_port(port_no):
#TODO: Validate the evc-map name
- from python.adapters.adtran.adtran_common.flow.evc_map import EVCMap
+ from pyvoltha.adapters.adtran_common.flow.evc_map import EVCMap
map_info = EVCMap.decode_evc_map_name(evc_map)
logical_port_no = int(map_info.get('ingress-port'))
@@ -1162,6 +1150,7 @@
self.adapter_agent.update_image_download(request)
+ @inlineCallbacks
def start_download(self, device, request, done):
"""
This is called to request downloading a specified image into
@@ -1193,7 +1182,7 @@
self._downloads[download.name] = download
self._update_download_status(request, download)
done.callback('started')
- return done
+ returnValue(done)
except Exception:
request.additional_info = 'Download request startup failed due to exception'
@@ -1214,9 +1203,10 @@
# restore admin state to enabled
device.admin_state = AdminState.ENABLED
- self.adapter_agent.update_device(device)
+ yield self.adapter_agent.device_update(device)
raise
+ @inlineCallbacks
def download_status(self, device, request, done):
"""
This is called to inquire about a requested image download status based
@@ -1241,11 +1231,12 @@
ImageDownload.DOWNLOAD_FAILED]:
# restore admin state to enabled
device.admin_state = AdminState.ENABLED
- self.adapter_agent.update_device(device)
+ yield self.adapter_agent.device_update(device)
done.callback(request.state)
- return done
+ returnValue(done)
+ @inlineCallbacks
def cancel_download(self, device, request, done):
"""
This is called to cancel a requested image download based on a NBI
@@ -1273,10 +1264,11 @@
if device.admin_state == AdminState.DOWNLOADING_IMAGE:
device.admin_state = AdminState.ENABLED
- self.adapter_agent.update_device(device)
+ yield self.adapter_agent.device_update(device)
- return done
+ returnValue(done)
+ @inlineCallbacks
def activate_image(self, device, request, done):
"""
This is called to activate a downloaded image from a standby partition
@@ -1306,9 +1298,10 @@
# restore admin state to enabled
device.admin_state = AdminState.ENABLED
- self.adapter_agent.update_device(device)
- return done
+ yield self.adapter_agent.device_update(device)
+ returnValue(done)
+ @inlineCallbacks
def revert_image(self, device, request, done):
"""
This is called to deactivate the specified image at active partition,
@@ -1338,8 +1331,8 @@
# restore admin state to enabled
device.admin_state = AdminState.ENABLED
- self.adapter_agent.update_device(device)
- return done
+ yield self.adapter_agent.device_update(device)
+ returnValue(done)
def add_onu_device(self, pon_id, onu_id, serial_number):
onu_device = self.adapter_agent.get_child_device(self.device_id,
diff --git a/adapters/adtran_olt/main.py b/adapters/adtran_olt/main.py
index 07bcc07..bea91bf 100755
--- a/adapters/adtran_olt/main.py
+++ b/adapters/adtran_olt/main.py
@@ -49,9 +49,9 @@
_ = third_party
-defs = dict(
- version_file='./VERSION',
- config=os.environ.get('CONFIG', './adapters-adtran_olt.yml'),
+defs=dict(
+ version_file='/voltha/VERSION',
+ config=os.environ.get('CONFIG', './adapters-adtran-olt.yml'),
container_name_regex=os.environ.get('CONTAINER_NUMBER_EXTRACTOR', '^.*\.(['
'0-9]+)\..*$'),
consul=os.environ.get('CONSUL', 'localhost:8500'),
@@ -64,8 +64,8 @@
core_topic=os.environ.get('CORE_TOPIC', 'rwcore'),
interface=os.environ.get('INTERFACE', get_my_primary_interface()),
instance_id=os.environ.get('INSTANCE_ID', os.environ.get('HOSTNAME', '1')),
- kafka_adapter=os.environ.get('KAFKA_ADAPTER', '172.20.10.3:9092'),
- kafka_cluster=os.environ.get('KAFKA_CLUSTER', '172.20.10.3:9092'),
+ kafka_adapter=os.environ.get('KAFKA_ADAPTER', '192.168.0.20:9092'),
+ kafka_cluster=os.environ.get('KAFKA_CLUSTER', '10.100.198.220:9092'),
backend=os.environ.get('BACKEND', 'none'),
retry_interval=os.environ.get('RETRY_INTERVAL', 2),
heartbeat_topic=os.environ.get('HEARTBEAT_TOPIC', "adapters.heartbeat"),
@@ -74,7 +74,7 @@
debug_enabled=True,
debug_host='work.bcsw.net',
# debug_host='10.0.2.15',
- debug_port=8765,
+ debug_port=5678,
)
@@ -286,7 +286,7 @@
except:
import sys
logger.error("pydevd startup exception: %s" % sys.exc_info()[0])
- print('REMOTE DEBUGGING will not be supported in this run...')
+ logger.error('REMOTE DEBUGGING will not be supported in this run...')
def load_config(args):
@@ -295,6 +295,7 @@
dir = os.path.dirname(os.path.abspath(__file__))
path = os.path.join(dir, path)
path = os.path.abspath(path)
+
with open(path) as fd:
config = yaml.load(fd)
return config
@@ -308,6 +309,7 @@
log.info(" / ____ \| |__| | | | | | \ \ / ____ \| |\ | | |__| | |____| | ")
log.info(" /_/ \_\_____/ |_| |_| _\_\/_/ \_\_| \_| \____/|______|_| ")
log.info(" /\ | | | | ")
+ log.info(' _ _ _ ')
log.info(" / \ __| | __ _ _ __ | |_ ___ _ __ ")
log.info(" / /\ \ / _` |/ _` | '_ \| __/ _ \ '__| ")
log.info(" / ____ \ (_| | (_| | |_) | || __/ | ")
@@ -322,42 +324,45 @@
class Main(object):
def __init__(self):
+ try:
+ self.args = args = parse_args()
+ self.config = load_config(args)
- self.args = args = parse_args()
- self.config = load_config(args)
+ verbosity_adjust = (args.verbose or 0) - (args.quiet or 0)
+ self.log = setup_logging(self.config.get('logging', {}),
+ args.instance_id,
+ verbosity_adjust=verbosity_adjust)
+ self.log.info('container-number-extractor',
+ regex=args.container_name_regex)
- verbosity_adjust = (args.verbose or 0) - (args.quiet or 0)
- self.log = setup_logging(self.config.get('logging', {}),
- args.instance_id,
- verbosity_adjust=verbosity_adjust)
- self.log.info('container-number-extractor',
- regex=args.container_name_regex)
+ if args.debug_enabled:
+ setup_remote_debug(args.debug_host, args.debug_port, self.log)
- if args.debug_enabled:
- setup_remote_debug(args.debug_host, args.debug_port, self.log)
+ self.adtran_olt_adapter_version = self.get_version()
+ self.log.info('ADTRAN-OLT-Adapter-Version',
+ version=self.adtran_olt_adapter_version)
- self.adtran_olt_adapter_version = self.get_version()
- self.log.info('ADTRAN-OLT-Adapter-Version', version=self.adtran_olt_adapter_version)
+ if not args.no_banner:
+ print_banner(self.log)
- if not args.no_banner:
- print_banner(self.log)
+ self.adapter = None
- self.adapter = None
- self.core_proxy = None
- self.adapter_proxy = None
+ # Create a unique instance id using the passed-in instance id and
+ # UTC timestamp
+ current_time = arrow.utcnow().timestamp
+ self.instance_id = self.args.instance_id + '_' + str(current_time)
- # Create a unique instance id using the passed-in instance id and
- # UTC timestamp
- current_time = arrow.utcnow().timestamp
- self.instance_id = self.args.instance_id + '_' + str(current_time)
+ self.core_topic = args.core_topic
+ self.listening_topic = args.name
+ self.startup_components()
- self.core_topic = args.core_topic
- self.listening_topic = args.name
- self.startup_components()
+ if not args.no_heartbeat:
+ self.start_heartbeat()
+ self.start_kafka_cluster_heartbeat(self.instance_id)
- if not args.no_heartbeat:
- self.start_heartbeat()
- self.start_kafka_cluster_heartbeat(self.instance_id)
+ except Exception as e:
+ self.log.exception('unhandled-exception', e=e)
+ raise
def get_version(self):
path = defs['version_file']
@@ -442,6 +447,7 @@
kv_store=self.args.backend,
default_topic=self.args.name,
group_id_prefix=self.args.instance_id,
+ # Needs to assign a real class
target_cls=adtran_request_handler
)
).start()
@@ -543,8 +549,8 @@
kafka_cluster_proxy.send_message(topic, dumps(message))
else:
self.log.error('kafka-proxy-unavailable')
- except Exception, err:
- self.log.exception('failed-sending-message-heartbeat', e=err)
+ except Exception as e:
+ self.log.exception('failed-sending-message-heartbeat', e=e)
try:
t0 = time.time()
diff --git a/adapters/adtran_olt/resources/adtran_olt_resource_manager.py b/adapters/adtran_olt/resources/adtran_olt_resource_manager.py
index caf5a46..8cce46c 100644
--- a/adapters/adtran_olt/resources/adtran_olt_resource_manager.py
+++ b/adapters/adtran_olt/resources/adtran_olt_resource_manager.py
@@ -245,7 +245,7 @@
# we need to derive the ONU Id for which the packet arrived based
# on the pon_intf and gemport available in the packet_indication
# self.kv_store[str(pon_intf_gemport)] = ' '.join(map(str, (onu_id, uni_id)))
- self.kv_store.put(self._make_path(str(pon_intf_gemport)), ' '.join(map(str, (onu_id, uni_id)))
+ self.kv_store.put(self._make_path(str(pon_intf_gemport)), ' '.join(map(str, (onu_id, uni_id))))
def get_onu_uni_from_ponport_gemport(self, pon_port, gemport):
pon_intf_gemport = (pon_port, gemport)
diff --git a/adapters/adtran_onu/adtran_onu.yml b/adapters/adtran_onu/adapters-adtran-onu.yml
similarity index 100%
rename from adapters/adtran_onu/adtran_onu.yml
rename to adapters/adtran_onu/adapters-adtran-onu.yml
diff --git a/adapters/adtran_onu/adtran_onu.py b/adapters/adtran_onu/adtran_onu.py
index c0801d1..7a88ed0 100755
--- a/adapters/adtran_onu/adtran_onu.py
+++ b/adapters/adtran_onu/adtran_onu.py
@@ -61,7 +61,7 @@
self.adtran_omci['omci-capabilities']['tasks']['get-capabilities'] = AdtnCapabilitiesTask
# TODO: Continue to customize adtran_omci here as needed
- self._omci_agent = OpenOMCIAgent(self.adapter_agent.core,
+ self._omci_agent = OpenOMCIAgent(self.adapter_agent,
support_classes=self.adtran_omci)
@property
diff --git a/adapters/adtran_onu/adtran_onu_handler.py b/adapters/adtran_onu/adtran_onu_handler.py
index 61fdc2c..beed980 100644
--- a/adapters/adtran_onu/adtran_onu_handler.py
+++ b/adapters/adtran_onu/adtran_onu_handler.py
@@ -212,9 +212,8 @@
assert device.parent_id, 'Invalid Parent ID'
assert device.proxy_address.device_id, 'Invalid Device ID'
- # register for proxied messages right away
+ # Cache our proxy address
self.proxy_address = device.proxy_address
- self.adapter_agent.register_for_proxied_messages(device.proxy_address)
# initialize device info
device.root = False
@@ -244,7 +243,7 @@
parent_device = self.adapter_agent.get_device(device.parent_id)
self.logical_device_id = parent_device.parent_id
- self.adapter_agent.update_device(device)
+ yield self.adapter_agent.device_update(device)
############################################################################
# Setup PM configuration for this device
@@ -260,7 +259,7 @@
pm_config = self.pm_metrics.make_proto()
self.openomci.set_pm_config(self.pm_metrics.omci_pm.openomci_interval_pm)
self.log.info("initial-pm-config", pm_config=pm_config)
- self.adapter_agent.update_device_pm_config(pm_config, init=True)
+ yield self.adapter_agent.device_pm_config_update(pm_config, init=True)
############################################################################
# Setup Alarm handler
@@ -276,8 +275,9 @@
device.reason = 'Failed to activate: {}'.format(e.message)
device.connect_status = ConnectStatus.UNREACHABLE
device.oper_status = OperStatus.FAILED
- self.adapter_agent.update_device(device)
+ self.adapter_agent.device_update(device)
+ @inlineCallbacks
def reconcile(self, device):
self.log.info('reconciling-ONU-device-starts')
@@ -294,19 +294,15 @@
# Register for adapter messages
self.adapter_agent.register_for_inter_adapter_messages()
- # Set the connection status to REACHABLE
- device.connect_status = ConnectStatus.REACHABLE
- self.adapter_agent.update_device(device)
- self.enabled = True
-
# TODO: Verify that the uni, pon and logical ports exists
+ self.enabled = True
# Mark the device as REACHABLE and ACTIVE
device = self.adapter_agent.get_device(device.id)
device.connect_status = ConnectStatus.REACHABLE
device.oper_status = OperStatus.ACTIVE
device.reason = ''
- self.adapter_agent.update_device(device)
+ yield self.adapter_agent.device_update(device)
self.log.info('reconciling-ONU-device-ends')
@@ -425,6 +421,7 @@
downstream = tp['downstream_gem_port_attribute_list']
self._create_gemports(upstream, downstream, tcont, uni_id, tech_profile_id)
+ @inlineCallbacks
def load_and_configure_tech_profile(self, uni_id, tp_path):
self.log.debug("loading-tech-profile-configuration", uni_id=uni_id, tp_path=tp_path)
@@ -442,7 +439,7 @@
if tp_path in self._tp_service_specific_task[uni_id]:
self.log.info("tech-profile-config-already-in-progress",
tp_path=tp_path)
- return
+ returnValue('already-in-progress')
tp = self.kv_client[tp_path]
tp = ast.literal_eval(tp)
@@ -455,7 +452,7 @@
self.log.info("tech-profile-config-done-successfully")
device = self.adapter_agent.get_device(self.device_id)
device.reason = ''
- self.adapter_agent.update_device(device)
+ yield self.adapter_agent.device_update(device)
if tp_path in self._tp_service_specific_task[uni_id]:
del self._tp_service_specific_task[uni_id][tp_path]
@@ -466,7 +463,7 @@
self.log.warn('tech-profile-config-failure-retrying', reason=_reason)
device = self.adapter_agent.get_device(self.device_id)
device.reason = 'Tech Profile config failed-retrying'
- self.adapter_agent.update_device(device)
+ yield self.adapter_agent.device_update(device)
if tp_path in self._tp_service_specific_task[uni_id]:
del self._tp_service_specific_task[uni_id][tp_path]
@@ -601,7 +598,7 @@
device.oper_status = OperStatus.ACTIVATING
device.connect_status = ConnectStatus.UNREACHABLE
device.reason = 'Attempting reboot'
- self.adapter_agent.update_device(device)
+ yield self.adapter_agent.device_update(device)
# TODO: send alert and clear alert after the reboot
try:
@@ -617,10 +614,10 @@
# Go ahead and pause less than that and start to look
# for it being alive
device.reason = 'reboot in progress'
- self.adapter_agent.update_device(device)
+ yield self.adapter_agent.device_update(device)
# Disable OpenOMCI
- self.omci.enabled = False
+ self.openomci.enabled = False
self._deferred = reactor.callLater(_ONU_REBOOT_MIN,
self._finish_reboot,
previous_oper_status,
@@ -631,13 +628,13 @@
def _finish_reboot(self, previous_oper_status, previous_conn_status,
reregister):
# Restart OpenOMCI
- self.omci.enabled = True
+ self.openomci.enabled = True
device = self.adapter_agent.get_device(self.device_id)
device.oper_status = previous_oper_status
device.connect_status = previous_conn_status
device.reason = ''
- self.adapter_agent.update_device(device)
+ yield self.adapter_agent.device_update(device)
if reregister:
self.adapter_agent.register_for_inter_adapter_messages()
@@ -655,6 +652,7 @@
# TODO: Support self test?
return SelfTestResponse(result=SelfTestResponse.NOT_SUPPORTED)
+ @inlineCallbacks
def disable(self):
self.log.info('disabling', device_id=self.device_id)
try:
@@ -668,7 +666,7 @@
device.oper_status = OperStatus.UNKNOWN
device.connect_status = ConnectStatus.UNREACHABLE
device.reason = 'Disabled'
- self.adapter_agent.update_device(device)
+ yield self.adapter_agent.device_update(device)
# Remove the uni logical port from the OLT, if still present
parent_device = self.adapter_agent.get_device(device.parent_id)
@@ -702,6 +700,7 @@
self.enabled = False
self.log.info('disabled')
+ @inlineCallbacks
def reenable(self):
self.log.info('re-enabling', device_id=self.device_id)
try:
@@ -729,7 +728,7 @@
self._pon.get_port())
# Update the connect status to REACHABLE
device.connect_status = ConnectStatus.REACHABLE
- self.adapter_agent.update_device(device)
+ yield self.adapter_agent.device_update(device)
# re-add uni port to logical device
parent_device = self.adapter_agent.get_device(device.parent_id)
@@ -748,7 +747,7 @@
device.reason = ''
self.enabled = True
- self.adapter_agent.update_device(device)
+ yield self.adapter_agent.device_update(device)
self.log.info('re-enabled')
@@ -773,6 +772,7 @@
omci, self._openomci = self._openomci, None
omci.delete()
+ @inlineCallbacks
def add_uni_ports(self):
""" Called after in-sync achieved and not in xPON mode"""
# TODO: We have to methods adding UNI ports. Go to one
@@ -823,7 +823,7 @@
pon_port.peers[d[0]].port_no = uni_port.port_number
self.adapter_agent.add_port_reference_to_parent(self.device_id,
pon_port)
- self.adapter_agent.update_device(device)
+ yield self.adapter_agent.device_update(device)
uni_port.enabled = True
uni_id += 1
diff --git a/adapters/adtran_onu/main.py b/adapters/adtran_onu/main.py
index e19f320..8bff56d 100755
--- a/adapters/adtran_onu/main.py
+++ b/adapters/adtran_onu/main.py
@@ -45,13 +45,14 @@
from adtran_onu import AdtranOnuAdapter
from pyvoltha.protos import third_party
from pyvoltha.protos.adapter_pb2 import AdapterConfig
+import sys
_ = third_party
-defs = dict(
- version_file='./VERSION',
- config=os.environ.get('CONFIG', './adapters-adtran_onu.yml'),
+defs=dict(
+ version_file='/voltha/VERSION',
+ config=os.environ.get('CONFIG', './adapters-adtran-onu.yml'),
container_name_regex=os.environ.get('CONTAINER_NUMBER_EXTRACTOR', '^.*\.(['
'0-9]+)\..*$'),
consul=os.environ.get('CONSUL', 'localhost:8500'),
@@ -74,7 +75,7 @@
debug_enabled=True,
debug_host='work.bcsw.net',
# debug_host='10.0.2.15',
- debug_port=5678,
+ debug_port=8765,
)
@@ -322,42 +323,48 @@
class Main(object):
def __init__(self):
+ try:
+ self.args = args = parse_args()
+ self.config = load_config(args)
- self.args = args = parse_args()
- self.config = load_config(args)
+ verbosity_adjust = (args.verbose or 0) - (args.quiet or 0)
+ self.log = setup_logging(self.config.get('logging', {}),
+ args.instance_id,
+ verbosity_adjust=verbosity_adjust)
+ self.log.info('container-number-extractor',
+ regex=args.container_name_regex)
- verbosity_adjust = (args.verbose or 0) - (args.quiet or 0)
- self.log = setup_logging(self.config.get('logging', {}),
- args.instance_id,
- verbosity_adjust=verbosity_adjust)
- self.log.info('container-number-extractor',
- regex=args.container_name_regex)
+ if args.debug_enabled:
+ setup_remote_debug(args.debug_host, args.debug_port, self.log)
- if args.debug_enabled:
- setup_remote_debug(args.debug_host, args.debug_port, self.log)
+ self.adtran_onu_adapter_version = self.get_version()
+ self.log.info('ADTRAN-ONU-Adapter-Version', version=self.adtran_onu_adapter_version)
- self.adtran_onu_adapter_version = self.get_version()
- self.log.info('ADTRAN-ONU-Adapter-Version', version=self.adtran_onu_adapter_version)
+ if not args.no_banner:
+ print_banner(self.log)
- if not args.no_banner:
- print_banner(self.log)
+ self.adapter = None
+ self.core_proxy = None
+ self.adapter_proxy = None
- self.adapter = None
- self.core_proxy = None
- self.adapter_proxy = None
+ # Create a unique instance id using the passed-in instance id and
+ # UTC timestamp
+ current_time = arrow.utcnow().timestamp
+ self.instance_id = self.args.instance_id + '_' + str(current_time)
- # Create a unique instance id using the passed-in instance id and
- # UTC timestamp
- current_time = arrow.utcnow().timestamp
- self.instance_id = self.args.instance_id + '_' + str(current_time)
+ self.core_topic = args.core_topic
+ self.listening_topic = args.name
+ self.startup_components()
- self.core_topic = args.core_topic
- self.listening_topic = args.name
- self.startup_components()
+ if not args.no_heartbeat:
+ self.start_heartbeat()
+ self.start_kafka_cluster_heartbeat(self.instance_id)
- if not args.no_heartbeat:
- self.start_heartbeat()
- self.start_kafka_cluster_heartbeat(self.instance_id)
+ except Exception as e:
+ self.log.exception('unhandled-exception', e=e)
+ for tick in xrange(0, 30):
+ import time
+ time.sleep(2)
def get_version(self):
path = defs['version_file']
diff --git a/adapters/adtran_onu/pon_port.py b/adapters/adtran_onu/pon_port.py
index fd0d0c1..c89815f 100644
--- a/adapters/adtran_onu/pon_port.py
+++ b/adapters/adtran_onu/pon_port.py
@@ -150,6 +150,7 @@
port_no=device.parent_port_no)])
return self._port
+ @inlineCallbacks
def _update_adapter_agent(self):
"""
Update the port status and state in the core
@@ -161,11 +162,13 @@
self._port.admin_state = self._admin_state
self._port.oper_status = self._oper_status
- # adapter_agent add_port also does an update of port status
- try:
- self._handler.adapter_agent.add_port(self._handler.device_id, self.get_port())
- except Exception as e:
- self.log.exception('update-port', e=e)
+ try:
+ yield self._handler.adapter_agent.port_state_update(self._handler.device_id,
+ self._port.type,
+ self._port.port_no,
+ self._port.oper_status)
+ except Exception as e:
+ self.log.exception('update-port', e=e)
def add_tcont(self, tcont, reflow=False):
"""
diff --git a/adapters/adtran_onu/uni_port.py b/adapters/adtran_onu/uni_port.py
index 96cd353..b829499 100644
--- a/adapters/adtran_onu/uni_port.py
+++ b/adapters/adtran_onu/uni_port.py
@@ -19,7 +19,8 @@
from pyvoltha.protos.logical_device_pb2 import LogicalPort
from pyvoltha.protos.openflow_13_pb2 import OFPPS_LIVE, OFPPF_FIBER
from pyvoltha.protos.openflow_13_pb2 import ofp_port
-import adtran_olt.resources.adtranolt_platform as platform
+# import adtran_olt.resources.adtranolt_platform as platform
+from twisted.internet.defer import inlineCallbacks
class UniPort(object):
@@ -136,6 +137,7 @@
"""
return self._logical_port_number
+ @inlineCallbacks
def _update_adapter_agent(self):
"""
Update the port status and state in the core
@@ -147,14 +149,16 @@
self._port.admin_state = self._admin_state
self._port.oper_status = self._oper_status
- try:
- # adapter_agent add_port also does an update of existing port
- self._handler.adapter_agent.add_port(self._handler.device_id,
- self.get_port())
- except KeyError: # Expected exception during ONU disabling
- pass
- except Exception as e: # Expected exception during ONU disabling
- self.log.exception('update-port', e=e)
+ try:
+ yield self._handler.adapter_agent.port_state_update(self._handler.device_id,
+ self._port.type,
+ self._port.port_no,
+ self._port.oper_status)
+
+ except KeyError: # Expected exception during ONU disabling
+ pass
+ except Exception as e: # Expected exception during ONU disabling
+ self.log.exception('update-port', e=e)
def get_port(self):
"""
diff --git a/compose/adapters-adtran_olt.yml b/compose/adapters-adtran-olt.yml
similarity index 77%
rename from compose/adapters-adtran_olt.yml
rename to compose/adapters-adtran-olt.yml
index 6489c20..3dedce2 100644
--- a/compose/adapters-adtran_olt.yml
+++ b/compose/adapters-adtran-olt.yml
@@ -15,24 +15,21 @@
version: '2'
services:
- ponsim_olt:
+ adtran_olt:
image: "${REGISTRY}${REPOSITORY}voltha-adapter-adtran-olt${TAG}"
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
- entrypoint:
- - /app/adtran_olt
- - -device_type
- - "OLT"
- - -internal_if
- - "eth0"
- - -external_if
- - "eth0"
- - -verbose
- ports:
- - "50060:50060"
+ command: [
+ "/voltha/adapters/adtran_olt/main.py",
+ "-v",
+ "--name=adtran_olt",
+ "--kafka_adapter=${DOCKER_HOST_IP}:9092",
+ "--kafka_cluster=${DOCKER_HOST_IP}:9092",
+ "--core_topic=rwcore"
+ ]
networks:
- default
diff --git a/compose/adapters-adtran_onu.yml b/compose/adapters-adtran-onu.yml
similarity index 77%
rename from compose/adapters-adtran_onu.yml
rename to compose/adapters-adtran-onu.yml
index 839d206..ca58676 100644
--- a/compose/adapters-adtran_onu.yml
+++ b/compose/adapters-adtran-onu.yml
@@ -15,24 +15,21 @@
version: '2'
services:
- ponsim_onu:
+ adtran_onu:
image: "${REGISTRY}${REPOSITORY}voltha-adapter-adtran-onu${TAG}"
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
- entrypoint:
- - /app/adtran_onu
- - -device_type
- - "OLT"
- - -internal_if
- - "eth0"
- - -external_if
- - "eth0"
- - -verbose
- ports:
- - "50061:50061"
+ command: [
+ "/voltha/adapters/adtran_onu/main.py",
+ "-v",
+ "--name=adtran_onu",
+ "--kafka_adapter=${DOCKER_HOST_IP}:9092",
+ "--kafka_cluster=${DOCKER_HOST_IP}:9092",
+ "--core_topic=rwcore"
+ ]
networks:
- default
diff --git a/compose/system-test.yml b/compose/system-test.yml
new file mode 100644
index 0000000..80646c9
--- /dev/null
+++ b/compose/system-test.yml
@@ -0,0 +1,180 @@
+---
+# 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.
+
+version: '2'
+
+networks:
+ default:
+ driver: bridge
+
+services:
+
+ zookeeper:
+ image: "wurstmeister/zookeeper:latest"
+ environment:
+ SERVICE_2181_NAME: "zookeeper"
+ ports:
+ - 2181:2181
+ networks:
+ - default
+
+
+ kafka:
+ image: "wurstmeister/kafka:2.11-2.0.1"
+ environment:
+ KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://${DOCKER_HOST_IP}:9092
+ KAFKA_LISTENERS: PLAINTEXT://:9092
+ KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
+ KAFKA_AUTO_CREATE_TOPICS_ENABLE: 'true'
+ SERVICE_9092_NAME: "kafka"
+ volumes:
+ - /var/run/docker.sock:/var/run/docker.sock
+ ports:
+ - 9092:9092
+ networks:
+ - default
+
+
+ etcd:
+ image: "quay.io/coreos/etcd:v3.2.9"
+ command: [
+ "etcd",
+ "--name=etcd0",
+ "--advertise-client-urls=http://${DOCKER_HOST_IP}:2379,http://${DOCKER_HOST_IP}:4001",
+ "--listen-client-urls=http://0.0.0.0:2379,http://0.0.0.0:4001",
+ "--initial-advertise-peer-urls=http://${DOCKER_HOST_IP}:2380",
+ "--listen-peer-urls=http://0.0.0.0:2380",
+ "--initial-cluster-token=etcd-cluster-1",
+ "--initial-cluster=etcd0=http://${DOCKER_HOST_IP}:2380",
+ "--initial-cluster-state=new"
+ ]
+ ports:
+ - "2379:2379"
+ - 2380
+ - 4001
+ networks:
+ - default
+
+
+ rw_core:
+ image: voltha-rw-core
+ entrypoint:
+ - /app/rw_core
+ - -kv_store_type=etcd
+ - -kv_store_host=${DOCKER_HOST_IP}
+ - -kv_store_port=2379
+ - -grpc_port=50057
+ - -banner=true
+ - -kafka_adapter_host=${DOCKER_HOST_IP}
+ - -kafka_adapter_port=9092
+ - -kafka_cluster_host=${DOCKER_HOST_IP}
+ - -kafka_cluster_port=9092
+ - -rw_core_topic=rwcore
+ - -kv_store_data_prefix=service/voltha
+ - -in_competing_mode=false
+ - -log_level=0
+ volumes:
+ - "/var/run/docker.sock:/tmp/docker.sock"
+ ports:
+ - 50057:50057
+ networks:
+ - default
+ restart: unless-stopped
+
+
+ cli:
+ image: "${REGISTRY}${REPOSITORY}voltha-cli:latest"
+ logging:
+ driver: "json-file"
+ options:
+ max-size: "10m"
+ max-file: "3"
+ environment:
+ DOCKER_HOST_IP: "${DOCKER_HOST_IP}"
+ entrypoint:
+ - /voltha/python/cli/setup.sh
+ - -g ${DOCKER_HOST_IP}:50057
+ networks:
+ - default
+ ports:
+ - "5022:22"
+
+
+ ofagent:
+ image: "${REGISTRY}${REPOSITORY}voltha-ofagent:latest"
+ logging:
+ driver: "json-file"
+ options:
+ max-size: "10m"
+ max-file: "3"
+ command: [
+ "/ofagent/ofagent/main.py",
+ "--consul=${DOCKER_HOST_IP}:8500",
+ "--controller=${DOCKER_HOST_IP}:6653",
+ "--grpc-endpoint=${DOCKER_HOST_IP}:50057",
+ "--instance-id-is-container-name",
+ "-v"
+ ]
+ volumes:
+ - "/var/run/docker.sock:/tmp/docker.sock"
+ networks:
+ - default
+ restart: unless-stopped
+
+
+ adapter_adtran_olt:
+ image: "${REGISTRY}${REPOSITORY}voltha-adapter-adtran-olt${TAG}"
+ logging:
+ driver: "json-file"
+ options:
+ max-size: "10m"
+ max-file: "3"
+ command: [
+ "/voltha/adapters/adtran_olt/main.py",
+ "-v",
+ "--name=adtran_olt",
+ "--kafka_adapter=${DOCKER_HOST_IP}:9092",
+ "--kafka_cluster=${DOCKER_HOST_IP}:9092",
+ "--backend=etcd",
+ "--etcd=${DOCKER_HOST_IP}:2379",
+ "--core_topic=rwcore"
+ ]
+ networks:
+ - default
+ restart: unless-stopped
+ depends_on:
+ - rw_core
+
+# adapter_adtran_onu:
+# image: "${REGISTRY}${REPOSITORY}voltha-adapter-adtran-onu${TAG}"
+# logging:
+# driver: "json-file"
+# options:
+# max-size: "10m"
+# max-file: "3"
+# command: [
+# "/voltha/adapters/adtran_onu/main.py",
+# "-v",
+# "--name=adtran_onu",
+# "--kafka_adapter=${DOCKER_HOST_IP}:9092",
+# "--kafka_cluster=${DOCKER_HOST_IP}:9092",
+# "--core_topic=rwcore"
+# ]
+# networks:
+# - default
+# restart: unless-stopped
+# depends_on:
+# - rw_core
+
diff --git a/docker/Dockerfile.adapter_adtran_olt b/docker/Dockerfile.adapter_adtran_olt
index 638b5b7..bc86c8a 100644
--- a/docker/Dockerfile.adapter_adtran_olt
+++ b/docker/Dockerfile.adapter_adtran_olt
@@ -21,6 +21,7 @@
# Adtran specific
COPY adapters/adtran_olt /voltha/adapters/adtran_olt
+COPY VERSION /voltha
# Exposing process and default entry point
CMD ["python", "/voltha/adapters/adtran_olt/main.py"]
diff --git a/docker/Dockerfile.adapter_adtran_olt_pyvoltha b/docker/Dockerfile.adapter_adtran_olt_pyvoltha
index 369ca8c..ab75613 100644
--- a/docker/Dockerfile.adapter_adtran_olt_pyvoltha
+++ b/docker/Dockerfile.adapter_adtran_olt_pyvoltha
@@ -19,8 +19,11 @@
MAINTAINER Voltha Community <info@opennetworking.org>
+ENV PYTHONPATH=/voltha
+
# Adtran specific
COPY adapters/adtran_olt /voltha/adapters/adtran_olt
+COPY VERSION /voltha
# Exposing process and default entry point
CMD ["python", "/voltha/adapters/adtran_olt/main.py"]
diff --git a/docker/Dockerfile.adapter_adtran_onu b/docker/Dockerfile.adapter_adtran_onu
index 3484dfb..be729a1 100644
--- a/docker/Dockerfile.adapter_adtran_onu
+++ b/docker/Dockerfile.adapter_adtran_onu
@@ -21,6 +21,7 @@
# Adtran specific
COPY adapters/adtran_olt /voltha/adapters/adtran_onu
+COPY VERSION /voltha
# Exposing process and default entry point
CMD ["python", "/voltha/adapters/adtran_onu/main.py"]
diff --git a/docker/Dockerfile.adapter_adtranonu_pyvoltha b/docker/Dockerfile.adapter_adtranonu_pyvoltha
index 6fcea60..0050ac7 100644
--- a/docker/Dockerfile.adapter_adtranonu_pyvoltha
+++ b/docker/Dockerfile.adapter_adtranonu_pyvoltha
@@ -21,6 +21,7 @@
# Adtran specific
COPY adapters/adtran_olt /voltha/adapters/adtran_onu
+COPY VERSION /voltha
# Exposing process and default entry point
CMD ["python", "/voltha/adapters/adtran_onu/main.py"]
\ No newline at end of file
diff --git a/docker/Dockerfile.base b/docker/Dockerfile.base
index b65e77b..8e9d461 100644
--- a/docker/Dockerfile.base
+++ b/docker/Dockerfile.base
@@ -35,7 +35,7 @@
COPY pki /voltha/pki/
-# Adtran specific
+# Adtran specific (common library and debug support)
COPY adapters/adtran_common /voltha/adapters/adtran_common
COPY pydevd /voltha/pydevd
diff --git a/docker/Dockerfile.base_local b/docker/Dockerfile.base_local
index 802e93f..792c2eb 100644
--- a/docker/Dockerfile.base_local
+++ b/docker/Dockerfile.base_local
@@ -35,7 +35,7 @@
COPY pki /voltha/pki/
-# Adtran specific
+# Adtran specific (common library and debug support)
COPY adapters/adtran_common /voltha/adapters/adtran_common
COPY pydevd /voltha/pydevd
@@ -43,3 +43,7 @@
COPY pyvoltha/dist /pyvoltha/dist
RUN pip install /pyvoltha/dist/*.tar.gz
+# Install local voltha-protos
+COPY voltha-protos/dist /voltha-protos/dist
+RUN pip install /voltha-protos/dist/*.tar.gz
+
diff --git a/docker/config/Makefile.protos b/docker/config/Makefile.protos
new file mode 100644
index 0000000..12ff9e3
--- /dev/null
+++ b/docker/config/Makefile.protos
@@ -0,0 +1,59 @@
+#
+# 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.
+#
+
+# Makefile to build all protobuf and gRPC related artifacts
+
+default: build
+
+PROTO_FILES := $(wildcard *.proto)
+PROTO_ALL_FILES := $(PROTO_FILES) $(PROTO_GOOGLE_API)
+PROTO_PB2_FILES := $(foreach f,$(PROTO_FILES),$(subst .proto,_pb2.py,$(f)))
+PROTO_PB2_GOOGLE_API := $(foreach f,$(PROTO_GOOGLE_API),$(subst .proto,_pb2.py,$(f)))
+PROTO_All_PB2_C_FILES := $(foreach f,$(PROTO_ALL_FILES),$(subst .proto,_pb2.pyc,$(f)))
+PROTO_ALL_PB2_GPRC_FILES := $(foreach f,$(PROTO_ALL_FILES),$(subst .proto,_pb2_grpc.py,$(f)))
+PROTO_ALL_DESC_FILES := $(foreach f,$(PROTO_ALL_FILES),$(subst .proto,.desc,$(f)))
+
+# Google API needs to be built from within the third party directory
+#
+google_api:
+ python -m grpc.tools.protoc \
+ -I. \
+ --python_out=. \
+ --grpc_python_out=. \
+ --descriptor_set_out=google/api/annotations.desc \
+ --include_imports \
+ --include_source_info \
+ google/api/annotations.proto google/api/http.proto
+
+build: $(PROTO_PB2_FILES)
+
+%_pb2.py: %.proto
+ python -m grpc.tools.protoc \
+ -I. \
+ -I/protos \
+ --python_out=. \
+ --grpc_python_out=. \
+ --descriptor_set_out=$(basename $<).desc \
+ --include_imports \
+ --include_source_info \
+ $<
+
+clean:
+ rm -f $(PROTO_PB2_FILES) \
+ $(PROTO_ALL_DESC_FILES) \
+ $(PROTO_ALL_PB2_GPRC_FILES) \
+ $(PROTO_All_PB2_C_FILES) \
+ $(PROTO_PB2_GOOGLE_API)
diff --git a/env.sh b/env.sh
index ec3b52f..8f6fffb 100644
--- a/env.sh
+++ b/env.sh
@@ -27,3 +27,4 @@
# add top-level voltha dir to pythonpath
export PYTHONPATH=$VOLTHA_BASE/$VENVDIR/lib/python2.7/site-packages:$PYTHONPATH:$VOLTHA_BASE:$VOLTHA_BASE/cli:$VOLTHA_BASE/protos/third_party
+export PATH=$VOLTHA_BASE/bin:$VOLTHA_BASE/bin/k8s:$PATH
diff --git a/k8s/README.md b/k8s/README.md
new file mode 100644
index 0000000..9d9a36f
--- /dev/null
+++ b/k8s/README.md
@@ -0,0 +1,38 @@
+## How to deploy read/write core pairs on Kubernetes
+
+The current technique installs a separate rw-core deployment to each Kubernetes node, where each deployment consists of a pair (replicas = 2) of co-located rw-cores. Co-location is enforced by making use of the Kubernetes nodeSelector constraint applied at the pod spec level.
+
+In order for node selection to work, a label must be applied to each node. There is a set of built-in node labels that comes with Kubernetes out of the box, one of which is kubernetes.io/hostname. This label can be used to constrain the deployment of a core pair to a node with a specific hostname. Another approach is to take greater control and create new node labels.
+
+The following discussion assumes installation of the voltha-k8s-playground (https://github.com/ciena/voltha-k8s-playground) which configures three Kubernetes nodes named k8s1, k8s2, and k8s3.
+
+Create a "nodename" label for each Kubernetes node:
+```
+kubectl label nodes k8s1 nodename=k8s1
+kubectl label nodes k8s2 nodename=k8s2
+kubectl label nodes k8s3 nodename=k8s3
+```
+
+Verify that the labels have been applied:
+```
+kubectl get nodes --show-labels
+NAME STATUS ROLES AGE VERSION LABELS
+k8s1 Ready master,node 4h v1.9.5 ...,kubernetes.io/hostname=k8s1,nodename=k8s1
+k8s2 Ready node 4h v1.9.5 ...,kubernetes.io/hostname=k8s2,nodename=k8s2
+k8s3 Ready node 4h v1.9.5 ...,kubernetes.io/hostname=k8s3,nodename=k8s3
+```
+
+
+Ensure that a nodeSelector section appears in the deployment's pod spec (such a section should already exist in each manifest):
+```
+ ...
+ nodeSelector:
+ nodename: k8s1
+```
+
+Once the labels have been applied, deploy the 3 core pairs:
+```
+kubectl apply -f k8s/rw-core-pair1.yml
+kubectl apply -f k8s/rw-core-pair2.yml
+kubectl apply -f k8s/rw-core-pair3.yml
+```
diff --git a/k8s/adapters-adtran-olt.yml b/k8s/adapters-adtran-olt.yml
new file mode 100644
index 0000000..1c61f83
--- /dev/null
+++ b/k8s/adapters-adtran-olt.yml
@@ -0,0 +1,59 @@
+# 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.
+
+# ADTRAN OLT adapter
+
+apiVersion: v1
+kind: Service
+metadata:
+ name: adapter-adtran-olt
+ namespace: voltha
+spec:
+ clusterIP: None
+ selector:
+ app: adapter-adtran-olt
+---
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: adapter-adtran-olt
+ namespace: voltha
+spec:
+ replicas: 1
+ selector:
+ matchLabels:
+ app: adapter-adtran-olt
+ template:
+ metadata:
+ labels:
+ app: adapter-adtran-olt
+ annotations:
+ cni: "calico"
+ spec:
+ containers:
+ - name: adapter-adtran-olt
+ image: voltha-adapter-adtran-olt
+ env:
+ - name: NAMESPACE
+ valueFrom:
+ fieldRef:
+ fieldPath: metadata.namespace
+ args:
+ - "/voltha/python/adapters/adtran/adtran_olt/main.py"
+ - "-v"
+ - "--name=adtran_olt"
+ - "--kafka_adapter=kafka.$(NAMESPACE).svc.cluster.local:9092"
+ - "--kafka_cluster=kafka.$(NAMESPACE).svc.cluster.local:9092"
+ - "--core_topic=rwcore"
+ imagePullPolicy: IfNotPresent
diff --git a/k8s/adapters-adtran-onu.yml b/k8s/adapters-adtran-onu.yml
new file mode 100644
index 0000000..a2f23c3
--- /dev/null
+++ b/k8s/adapters-adtran-onu.yml
@@ -0,0 +1,59 @@
+# 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.
+
+# ADTRAN OLT adapter
+
+apiVersion: v1
+kind: Service
+metadata:
+ name: adapter-adtran-onu
+ namespace: voltha
+spec:
+ clusterIP: None
+ selector:
+ app: adapter-adtran-onu
+---
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: adapter-adtran-onu
+ namespace: voltha
+spec:
+ replicas: 1
+ selector:
+ matchLabels:
+ app: adapter-adtran-onu
+ template:
+ metadata:
+ labels:
+ app: adapter-adtran-onu
+ annotations:
+ cni: "calico"
+ spec:
+ containers:
+ - name: adapter-adtran-onu
+ image: voltha-adapter-adtran-onu
+ env:
+ - name: NAMESPACE
+ valueFrom:
+ fieldRef:
+ fieldPath: metadata.namespace
+ args:
+ - "/voltha/python/adapters/adtran_onu/main.py"
+ - "-v"
+ - "--name=adtran_olt"
+ - "--kafka_adapter=kafka.$(NAMESPACE).svc.cluster.local:9092"
+ - "--kafka_cluster=kafka.$(NAMESPACE).svc.cluster.local:9092"
+ - "--core_topic=rwcore"
+ imagePullPolicy: IfNotPresent
diff --git a/k8s/single-node/cli.yml b/k8s/single-node/cli.yml
new file mode 100644
index 0000000..680d172
--- /dev/null
+++ b/k8s/single-node/cli.yml
@@ -0,0 +1,63 @@
+# 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.
+apiVersion: v1
+kind: Service
+metadata:
+ name: vcli
+ namespace: voltha
+ labels:
+ name: vcli
+spec:
+ ports:
+ - name: ssh
+ port: 5022
+ targetPort: 22
+ selector:
+ app: vcli
+---
+apiVersion: apps/v1beta1
+kind: Deployment
+metadata:
+ name: vcli
+ namespace: voltha
+spec:
+ replicas: 1
+ template:
+ metadata:
+ labels:
+ app: vcli
+ annotations:
+ cni: "calico"
+ spec:
+ containers:
+ - name: vcli
+ image: voltha-cli
+ env:
+ - name: POD_IP
+ valueFrom:
+ fieldRef:
+ fieldPath: status.podIP
+ - name: NAMESPACE
+ valueFrom:
+ fieldRef:
+ fieldPath: metadata.namespace
+ args:
+ - "/voltha/python/cli/setup.sh"
+ - "-g rw-core:50057"
+ ports:
+ - containerPort: 22
+ name: ssh-port
+ imagePullPolicy: Never
+
+
diff --git a/k8s/single-node/etcd-cluster.yml b/k8s/single-node/etcd-cluster.yml
new file mode 100644
index 0000000..61a35fa
--- /dev/null
+++ b/k8s/single-node/etcd-cluster.yml
@@ -0,0 +1,25 @@
+# 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.
+apiVersion: "etcd.database.coreos.com/v1beta2"
+kind: "EtcdCluster"
+metadata:
+ name: etcd
+ namespace: voltha
+spec:
+ size: 1
+ version: "3.2.18"
+ pod:
+ annotations:
+ cni: "calico"
+
diff --git a/k8s/single-node/kafka.yml b/k8s/single-node/kafka.yml
new file mode 100644
index 0000000..4604676
--- /dev/null
+++ b/k8s/single-node/kafka.yml
@@ -0,0 +1,58 @@
+# 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.
+apiVersion: v1
+kind: Service
+metadata:
+ name: kafka
+ namespace: voltha
+spec:
+ clusterIP: None
+ selector:
+ app: kafka
+ ports:
+ - protocol: TCP
+ port: 9092
+ targetPort: 9092
+---
+apiVersion: apps/v1beta1
+kind: StatefulSet
+metadata:
+ name: kafka
+ namespace: voltha
+spec:
+ serviceName: kafka
+ replicas: 1
+ selector:
+ matchLabels:
+ app: kafka
+ template:
+ metadata:
+ labels:
+ app: kafka
+ annotations:
+ cni: "calico"
+ spec:
+ terminationGracePeriodSeconds: 10
+ containers:
+ - name: kafka
+ image: wurstmeister/kafka:1.0.0
+ ports:
+ - containerPort: 9092
+ env:
+ - name: KAFKA_ADVERTISED_PORT
+ value: "9092"
+ - name: KAFKA_ZOOKEEPER_CONNECT
+ value: zoo:2181
+ - name: KAFKA_HEAP_OPTS
+ value: "-Xmx256M -Xms128M"
diff --git a/k8s/single-node/olt.yml b/k8s/single-node/olt.yml
new file mode 100644
index 0000000..148e1ad
--- /dev/null
+++ b/k8s/single-node/olt.yml
@@ -0,0 +1,74 @@
+# 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.
+apiVersion: v1
+kind: Service
+metadata:
+ name: olt
+ namespace: voltha
+ labels:
+ name: olt
+spec:
+ ports:
+ - name: grpc
+ port: 50060
+ targetPort: 50060
+ selector:
+ app: olt
+---
+apiVersion: apps/v1beta1
+kind: Deployment
+metadata:
+ name: olt
+ namespace: voltha
+spec:
+ replicas: 1
+ template:
+ metadata:
+ labels:
+ app: olt
+ annotations:
+ cni: "calico"
+ spec:
+ containers:
+ - name: olt
+ image: "voltha-ponsim:latest"
+ env:
+ - name: POD_IP
+ valueFrom:
+ fieldRef:
+ fieldPath: status.podIP
+ - name: NAMESPACE
+ valueFrom:
+ fieldRef:
+ fieldPath: metadata.namespace
+
+ args:
+ - "/app/ponsim"
+ - "-device_type"
+ - "OLT"
+ - "-onus"
+ - "1"
+ - "-internal_if"
+ - "eth0"
+ - "-external_if"
+ - "eth0"
+ - "-vcore_endpoint"
+ - "rw-core"
+ - "-promiscuous"
+ - "-verbose"
+ ports:
+ - containerPort: 50060
+ name: grpc-port
+
+ imagePullPolicy: Never
diff --git a/k8s/single-node/onu.yml b/k8s/single-node/onu.yml
new file mode 100644
index 0000000..38e6cc6
--- /dev/null
+++ b/k8s/single-node/onu.yml
@@ -0,0 +1,74 @@
+# 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.
+apiVersion: v1
+kind: Service
+metadata:
+ name: onu
+ namespace: voltha
+ labels:
+ name: onu
+spec:
+ ports:
+ - name: grpc
+ port: 50061
+ targetPort: 50061
+ selector:
+ app: onu
+---
+apiVersion: apps/v1beta1
+kind: Deployment
+metadata:
+ name: onu
+ namespace: voltha
+spec:
+ replicas: 1
+ template:
+ metadata:
+ labels:
+ app: onu
+ annotations:
+ cni: "calico,pon0"
+ spec:
+ containers:
+ - name: onu
+ image: "voltha-ponsim:latest"
+ env:
+ - name: POD_IP
+ valueFrom:
+ fieldRef:
+ fieldPath: status.podIP
+ - name: NAMESPACE
+ valueFrom:
+ fieldRef:
+ fieldPath: metadata.namespace
+
+ args:
+ - "/app/ponsim"
+ - "-device_type"
+ - "ONU"
+ - "-parent_addr"
+ - "olt"
+ - "-grpc_port"
+ - "50061"
+ - "-internal_if"
+ - "eth0"
+ - "-external_if"
+ - "eth1"
+ - "-promiscuous"
+ - "-verbose"
+ ports:
+ - containerPort: 50061
+ name: grpc-port
+
+ imagePullPolicy: Never
diff --git a/k8s/single-node/ro-core.yml b/k8s/single-node/ro-core.yml
new file mode 100644
index 0000000..b2f278f
--- /dev/null
+++ b/k8s/single-node/ro-core.yml
@@ -0,0 +1,73 @@
+# 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.
+
+apiVersion: v1
+kind: Service
+metadata:
+ name: ro-core
+ namespace: voltha
+spec:
+ clusterIP: None
+ ports:
+ - name: grpc
+ port: 50057
+ targetPort: 50057
+ selector:
+ app: ro-core
+---
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: ro-core
+ namespace: voltha
+spec:
+ replicas: 1
+ selector:
+ matchLabels:
+ app: ro-core
+ template:
+ metadata:
+ labels:
+ app: ro-core
+ annotations:
+ cni: "calico"
+ spec:
+ containers:
+ - name: voltha
+ image: voltha-ro-core
+ env:
+ - name: NAMESPACE
+ valueFrom:
+ fieldRef:
+ fieldPath: metadata.namespace
+ - name: POD_IP
+ valueFrom:
+ fieldRef:
+ fieldPath: status.podIP
+ args:
+ - "/app/ro_core"
+ - "-kv_store_type=etcd"
+ - "-kv_store_host=etcd.$(NAMESPACE).svc.cluster.local"
+ - "-kv_store_port=2379"
+ - "-grpc_port=50057"
+ - "-banner=true"
+ - "-ro_core_topic=rocore"
+ - "-log_level=0"
+ ports:
+ - containerPort: 50057
+ name: grpc-port
+ imagePullPolicy: IfNotPresent
+
+
+
diff --git a/k8s/single-node/rw-core.yml b/k8s/single-node/rw-core.yml
new file mode 100644
index 0000000..7fd3848
--- /dev/null
+++ b/k8s/single-node/rw-core.yml
@@ -0,0 +1,77 @@
+# 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.
+
+apiVersion: v1
+kind: Service
+metadata:
+ name: rw-core
+ namespace: voltha
+spec:
+ clusterIP: None
+ ports:
+ - name: grpc
+ port: 50057
+ targetPort: 50057
+ selector:
+ app: rw-core
+---
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: rw-core
+ namespace: voltha
+spec:
+ replicas: 1
+ selector:
+ matchLabels:
+ app: rw-core
+ template:
+ metadata:
+ labels:
+ app: rw-core
+ annotations:
+ cni: "calico"
+ spec:
+ containers:
+ - name: voltha
+ image: voltha-rw-core
+ env:
+ - name: NAMESPACE
+ valueFrom:
+ fieldRef:
+ fieldPath: metadata.namespace
+ - name: POD_IP
+ valueFrom:
+ fieldRef:
+ fieldPath: status.podIP
+ args:
+ - "/app/rw_core"
+ - "-kv_store_type=etcd"
+ - "-kv_store_host=etcd.$(NAMESPACE).svc.cluster.local"
+ - "-kv_store_port=2379"
+ - "-grpc_port=50057"
+ - "-banner=true"
+ - "-kafka_adapter_host=kafka.$(NAMESPACE).svc.cluster.local"
+ - "-kafka_adapter_port=9092"
+ - "-kafka_cluster_host=kafka.$(NAMESPACE).svc.cluster.local"
+ - "-kafka_cluster_port=9092"
+ - "-rw_core_topic=rwcore"
+ - "-log_level=0"
+ ports:
+ - containerPort: 50057
+ name: grpc-port
+ imagePullPolicy: IfNotPresent
+
+
+
diff --git a/k8s/single-node/zookeeper.yml b/k8s/single-node/zookeeper.yml
new file mode 100644
index 0000000..ffd3e12
--- /dev/null
+++ b/k8s/single-node/zookeeper.yml
@@ -0,0 +1,69 @@
+# 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.
+apiVersion: v1
+kind: Service
+metadata:
+ name: zoo
+ namespace: voltha
+spec:
+ clusterIP: None
+ selector:
+ app: zookeeper
+ ports:
+ - name: client
+ port: 2181
+ targetPort: 2181
+ - name: follower
+ port: 2888
+ targetPort: 2888
+ - name: leader
+ port: 3888
+ targetPort: 3888
+---
+apiVersion: apps/v1beta1
+kind: StatefulSet
+metadata:
+ name: zookeeper
+ namespace: voltha
+spec:
+ serviceName: zoo
+ replicas: 1
+ selector:
+ matchLabels:
+ app: zookeeper
+ template:
+ metadata:
+ labels:
+ app: zookeeper
+ annotations:
+ cni: "calico"
+ spec:
+ containers:
+ - name: zoo
+ image: zookeeper:3.4.11
+ ports:
+ - containerPort: 2181
+ - containerPort: 2888
+ - containerPort: 3888
+ env:
+ - name: NAMESPACE
+ valueFrom:
+ fieldRef:
+ fieldPath: metadata.namespace
+ - name: ZOO_MY_ID
+ value: "1"
+# - name: ZOO_SERVERS
+# value: >
+# server.1=zookeeper1-0.zoo1.$(NAMESPACE).svc.cluster.local:2888:3888
+
diff --git a/requirements.txt b/requirements.txt
index 0ccfe39..aa62e19 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,8 +1,9 @@
+lxml==3.6.4
ncclient==0.5.3
packaging==17.1
pyvoltha==0.1.7
-lxml==3.6.4
-zmq==0.0.0
pyzmq==16.0.3
txZMQ==0.8.0
+voltha-protos==0.1.0
xmltodict==0.11.0
+zmq==0.0.0