WIP [VOL-2811] - Incorporate preliminary onu-adapter-go code into opencord repo

- functionality: reason "initial-mib-downloaded" reached
- omciAgent removed, object relation restructured
- adapter code restructuring + internal lib interface update

Change-Id: Ie53450a5e2c093aaaf68fe652f95e7b4c4a014c7
Signed-off-by: Holger Hildebrandt <holger.hildebrandt@adtran.com>
diff --git a/internal/pkg/onuadaptercore/onu_device_entry.go b/internal/pkg/onuadaptercore/onu_device_entry.go
new file mode 100644
index 0000000..837dadb
--- /dev/null
+++ b/internal/pkg/onuadaptercore/onu_device_entry.go
@@ -0,0 +1,221 @@
+/*
+ * Copyright 2020-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.
+ */
+
+//Package adaptercoreonu provides the utility for onu devices, flows and statistics
+package adaptercoreonu
+
+import (
+	"context"
+	//"errors"
+	//"sync"
+	//"time"
+
+	"github.com/looplab/fsm"
+	"github.com/opencord/voltha-lib-go/v3/pkg/adapters/adapterif"
+
+	//"github.com/opencord/voltha-lib-go/v3/pkg/kafka"
+	"github.com/opencord/voltha-lib-go/v3/pkg/log"
+	//ic "github.com/opencord/voltha-protos/v3/go/inter_container"
+	//"github.com/opencord/voltha-protos/v3/go/openflow_13"
+	//"github.com/opencord/voltha-protos/v3/go/voltha"
+)
+
+type OnuDeviceEvent int
+
+const (
+	// Events of interest to Device Adapters and OpenOMCI State Machines
+	DeviceStatusInit     OnuDeviceEvent = 0 // OnuDeviceEntry default start state
+	MibDatabaseSync      OnuDeviceEvent = 1 // MIB database sync (upload done)
+	OmciCapabilitiesDone OnuDeviceEvent = 2 // OMCI ME and message type capabilities known
+	MibDownloadDone      OnuDeviceEvent = 3 // MIB database sync (upload done)
+	PortLinkUp           OnuDeviceEvent = 4 // Port link state change
+	PortLinkDw           OnuDeviceEvent = 5 // Port link state change
+	// Add other events here as needed (alarms separate???)
+)
+
+type activityDescr struct {
+	databaseClass   func() error
+	advertiseEvents bool
+	auditDelay      uint16
+	//tasks           map[string]func() error
+}
+type OmciDeviceFsms map[string]activityDescr
+
+//OntDeviceEntry structure holds information about the attached FSM'as and their communication
+type OnuDeviceEntry struct {
+	deviceID          string
+	baseDeviceHandler *DeviceHandler
+	coreProxy         adapterif.CoreProxy
+	adapterProxy      adapterif.AdapterProxy
+	started           bool
+	PDevOmciCC        *OmciCC
+	//lockDeviceEntries           sync.RWMutex
+	mibDbClass    func() error
+	supportedFsms OmciDeviceFsms
+	MibSyncFsm    *fsm.FSM
+	MibSyncChan   chan Message
+	devState      OnuDeviceEvent
+	mibAuditDelay uint16
+}
+
+//OnuDeviceEntry returns a new instance of a OnuDeviceEntry
+//mib_db (as well as not inluded alarm_db not really used in this code? VERIFY!!)
+func NewOnuDeviceEntry(ctx context.Context,
+	device_id string, device_Handler *DeviceHandler,
+	core_proxy adapterif.CoreProxy, adapter_proxy adapterif.AdapterProxy,
+	supported_Fsms_Ptr *OmciDeviceFsms) *OnuDeviceEntry {
+	logger.Infow("init-onuDeviceEntry", log.Fields{"deviceId": device_id})
+	var onuDeviceEntry OnuDeviceEntry
+	onuDeviceEntry.started = false
+	onuDeviceEntry.deviceID = device_id
+	onuDeviceEntry.baseDeviceHandler = device_Handler
+	onuDeviceEntry.coreProxy = core_proxy
+	onuDeviceEntry.adapterProxy = adapter_proxy
+	onuDeviceEntry.devState = DeviceStatusInit
+	//openomciagent.lockDeviceHandlersMap = sync.RWMutex{}
+	//OMCI related databases are on a per-agent basis. State machines and tasks
+	//are per ONU Vendor
+	//
+	// MIB Synchronization Database - possible overloading from arguments
+	if supported_Fsms_Ptr != nil {
+		onuDeviceEntry.supportedFsms = *supported_Fsms_Ptr
+	} else {
+		//var mibSyncFsm = NewMibSynchronizer()
+		// use some internaö defaults, if not defined from outside
+		onuDeviceEntry.supportedFsms = OmciDeviceFsms{
+			"mib-synchronizer": {
+				//mibSyncFsm,        // Implements the MIB synchronization state machine
+				onuDeviceEntry.MibDbVolatileDict, // Implements volatile ME MIB database
+				true,                             // Advertise events on OpenOMCI event bus
+				60,                               // Time to wait between MIB audits.  0 to disable audits.
+				// map[string]func() error{
+				// 	"mib-upload":    onuDeviceEntry.MibUploadTask,
+				// 	"mib-template":  onuDeviceEntry.MibTemplateTask,
+				// 	"get-mds":       onuDeviceEntry.GetMdsTask,
+				// 	"mib-audit":     onuDeviceEntry.GetMdsTask,
+				// 	"mib-resync":    onuDeviceEntry.MibResyncTask,
+				// 	"mib-reconcile": onuDeviceEntry.MibReconcileTask,
+				// },
+			},
+		}
+	}
+	onuDeviceEntry.mibDbClass = onuDeviceEntry.supportedFsms["mib-synchronizer"].databaseClass
+	logger.Debug("access2mibDbClass")
+	go onuDeviceEntry.mibDbClass()
+	onuDeviceEntry.mibAuditDelay = onuDeviceEntry.supportedFsms["mib-synchronizer"].auditDelay
+	logger.Debugw("MibAudit is set to", log.Fields{"Delay": onuDeviceEntry.mibAuditDelay})
+
+	// Omci related Mib sync state machine
+	onuDeviceEntry.MibSyncFsm = fsm.NewFSM(
+		"disabled",
+		fsm.Events{
+
+			{Name: "start", Src: []string{"disabled"}, Dst: "starting"},
+
+			{Name: "load_mib_template", Src: []string{"starting"}, Dst: "loading_mib_template"},
+			{Name: "upload_mib", Src: []string{"loading_mib_template"}, Dst: "uploading"},
+			{Name: "examine_mds", Src: []string{"starting"}, Dst: "examining_mds"},
+
+			{Name: "success", Src: []string{"loading_mib_template"}, Dst: "in_sync"},
+			{Name: "success", Src: []string{"uploading"}, Dst: "in_sync"},
+
+			{Name: "success", Src: []string{"examining_mds"}, Dst: "in_sync"},
+			{Name: "mismatch", Src: []string{"examining_mds"}, Dst: "resynchronizing"},
+
+			{Name: "audit_mib", Src: []string{"in_sync"}, Dst: "auditing"},
+
+			{Name: "success", Src: []string{"out_of_sync"}, Dst: "in_sync"},
+			{Name: "audit_mib", Src: []string{"out_of_sync"}, Dst: "auditing"},
+
+			{Name: "success", Src: []string{"auditing"}, Dst: "in_sync"},
+			{Name: "mismatch", Src: []string{"auditing"}, Dst: "resynchronizing"},
+			{Name: "force_resync", Src: []string{"auditing"}, Dst: "resynchronizing"},
+
+			{Name: "success", Src: []string{"resynchronizing"}, Dst: "in_sync"},
+			{Name: "diffs_found", Src: []string{"resynchronizing"}, Dst: "out_of_sync"},
+
+			{Name: "timeout", Src: []string{"loading_mib_template", "uploading", "resynchronizing", "examining_mds", "in_sync", "out_of_sync", "auditing"}, Dst: "starting"},
+
+			{Name: "stop", Src: []string{"starting", "loading_mib_template", "uploading", "resynchronizing", "examining_mds", "in_sync", "out_of_sync", "auditing"}, Dst: "disabled"},
+		},
+
+		fsm.Callbacks{
+			"enter_state":                func(e *fsm.Event) { onuDeviceEntry.logStateChange(e) },
+			"enter_starting":             func(e *fsm.Event) { onuDeviceEntry.enterStartingState(e) },
+			"enter_loading_mib_template": func(e *fsm.Event) { onuDeviceEntry.enterLoadingMibTemplateState(e) },
+			"enter_uploading":            func(e *fsm.Event) { onuDeviceEntry.enterUploadingState(e) },
+			"enter_examining_mds":        func(e *fsm.Event) { onuDeviceEntry.enterExaminingMdsState(e) },
+			"enter_resynchronizing":      func(e *fsm.Event) { onuDeviceEntry.enterResynchronizingState(e) },
+			"enter_auditing":             func(e *fsm.Event) { onuDeviceEntry.enterAuditingState(e) },
+			"enter_out_of_sync":          func(e *fsm.Event) { onuDeviceEntry.enterOutOfSyncState(e) },
+			"enter_in_sync":              func(e *fsm.Event) { onuDeviceEntry.enterInSyncState(e) },
+		},
+	)
+
+	// Alarm Synchronization Database
+	//self._alarm_db = None
+	//self._alarm_database_cls = support_classes['alarm-synchronizer']['database']
+	return &onuDeviceEntry
+}
+
+//Start starts (logs) the omci agent
+func (oo *OnuDeviceEntry) Start(ctx context.Context) error {
+	logger.Info("starting-OnuDeviceEntry")
+
+	oo.PDevOmciCC = NewOmciCC(ctx, oo, oo.deviceID, oo.baseDeviceHandler,
+		oo.coreProxy, oo.adapterProxy)
+
+	//TODO .....
+	//mib_db.start()
+	oo.started = true
+	logger.Info("OnuDeviceEntry-started, but not yet mib_db!!!")
+	return nil
+}
+
+//Stop terminates the session
+func (oo *OnuDeviceEntry) Stop(ctx context.Context) error {
+	logger.Info("stopping-OnuDeviceEntry")
+	oo.started = false
+	//oo.exitChannel <- 1
+	logger.Info("OnuDeviceEntry-stopped")
+	return nil
+}
+
+//Relay the InSync message via Handler to Rw core - Status update
+func (oo *OnuDeviceEntry) transferSystemEvent(dev_Event OnuDeviceEvent) error {
+	logger.Debugw("relaying system-event", log.Fields{"Event": dev_Event})
+	// decouple the handler transfer from further processing here
+	// TODO!!! check if really no synch is required within the system e.g. to ensure following steps ..
+	if dev_Event == MibDatabaseSync {
+		if oo.devState < MibDatabaseSync { //devState has not been synced yet
+			oo.devState = MibDatabaseSync
+			go oo.baseDeviceHandler.DeviceStateUpdate(dev_Event)
+			//TODO!!! device control: next step: start MIB capability verification from here ?!!!
+		} else {
+			logger.Debugw("mibinsync-event in some already synced state - ignored", log.Fields{"state": oo.devState})
+		}
+	} else if dev_Event == MibDownloadDone {
+		if oo.devState < MibDownloadDone { //devState has not been synced yet
+			oo.devState = MibDownloadDone
+			go oo.baseDeviceHandler.DeviceStateUpdate(dev_Event)
+		} else {
+			logger.Debugw("mibdownloaddone-event was already seen - ignored", log.Fields{"state": oo.devState})
+		}
+	} else {
+		logger.Warnw("device-event not yet handled", log.Fields{"state": dev_Event})
+	}
+	return nil
+}