First Commit of Voltha-Go-Controller from Radisys

Change-Id: I8e2e908e7ab09a4fe3d86849da18b6d69dcf4ab0
diff --git a/internal/pkg/vpagent/refresh.go b/internal/pkg/vpagent/refresh.go
new file mode 100644
index 0000000..c06e5cd
--- /dev/null
+++ b/internal/pkg/vpagent/refresh.go
@@ -0,0 +1,141 @@
+/*
+* Copyright 2022-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 vpagent
+
+import (
+	"context"
+	"time"
+
+	"voltha-go-controller/internal/pkg/intf"
+
+	"github.com/golang/protobuf/ptypes/empty"
+	"github.com/opencord/voltha-lib-go/v7/pkg/log"
+	"github.com/opencord/voltha-protos/v5/go/voltha"
+)
+
+func (vpa *VPAgent) synchronizeDeviceList(ctx context.Context) {
+	// Send reconnection indication to the devices already known
+	for _, vpc := range vpa.clientMap {
+		vpc.ConnectInd(context.TODO(), intf.DeviceReDisc)
+	}
+
+	// Refresh once to get everything started
+	vpa.refreshDeviceList()
+
+	tick := time.NewTicker(vpa.DeviceListRefreshInterval)
+loop:
+	for {
+		select {
+		case <-ctx.Done():
+			logger.Errorw(ctx, "Context Done", log.Fields{"Context": ctx})
+			break loop
+		case <-tick.C:
+			vpa.refreshDeviceList()
+		}
+	}
+	tick.Stop()
+}
+
+func (vpa *VPAgent) refreshDeviceList() {
+	// If we exit, assume disconnected
+	if vpa.volthaClient == nil {
+		logger.Error(ctx, "no-voltha-connection")
+		vpa.events <- vpaEventVolthaDisconnected
+		return
+	}
+	deviceList, err := vpa.volthaClient.Get().ListLogicalDevices(context.Background(), &empty.Empty{})
+	if err != nil {
+		logger.Errorw(ctx, "vpagent failed to query device list from voltha",
+			log.Fields{"error": err})
+		vpa.events <- vpaEventVolthaDisconnected
+		return
+	}
+
+	var toAdd []int
+	var toDel []string
+	var deviceIDMap = make(map[string]string)
+	for index, d := range deviceList.Items {
+		deviceID := d.Id
+		deviceIDMap[deviceID] = deviceID
+		if vpa.clientMap[deviceID] == nil {
+			toAdd = append(toAdd, index)
+		}
+	}
+	for key := range vpa.clientMap {
+		deviceID, ok := deviceIDMap[key]
+		if !ok || (ok && deviceID == "") {
+			toDel = append(toDel, key)
+		}
+	}
+	logger.Debugw(ctx, "Device Refresh", log.Fields{"ToAdd": toAdd, "ToDel": toDel})
+	for i := 0; i < len(toAdd); i++ {
+		device := deviceList.Items[toAdd[i]]
+		serialNum := device.Desc.SerialNum
+		// If the blocked device list contain device serial number, do not add VPClient.
+		if vpa.VPClientAgent.IsBlockedDevice(serialNum) {
+			logger.Debugw(ctx, "Device Serial Number is present in the blocked device list", log.Fields{"device-serial-number": serialNum})
+		} else {
+			vpa.addVPClient(device) // client is started in addVPClient
+		}
+	}
+
+	for i := 0; i < len(toDel); i++ {
+		vpa.VPClientAgent.DelDevice(toDel[i])
+		vpa.mapLock.Lock()
+		delete(vpa.clientMap, toDel[i])
+		vpa.mapLock.Unlock()
+	}
+}
+
+func (vpa *VPAgent) addVPClient(device *voltha.LogicalDevice) intf.IVPClient {
+	logger.Warnw(ctx, "GrpcClient addClient called ", log.Fields{"device-id": device.Id})
+	vpa.mapLock.Lock()
+	defer vpa.mapLock.Unlock()
+	var serialNum = "Unknown"
+	if device.Desc != nil {
+		serialNum = device.Desc.SerialNum
+	}
+	vpc := vpa.clientMap[device.Id]
+	if vpc == nil {
+		vpa.VPClientAgent.AddNewDevice(&intf.VPClientCfg{
+			DeviceID:         device.Id,
+			SerialNum:        serialNum,
+			SouthBoundID:     device.RootDeviceId,
+			VolthaClient:     vpa.volthaClient,
+			PacketOutChannel: vpa.packetOutChannel,
+		})
+
+	}
+	logger.Debugw(ctx, "Finished with addClient", log.Fields{"deviceID": device.Id})
+	return vpc
+}
+
+//AddClientToClientMap - called by controller once device obj is created
+func (vpa *VPAgent) AddClientToClientMap(deviceID string, vpc intf.IVPClient) {
+	vpa.mapLock.Lock()
+	defer vpa.mapLock.Unlock()
+
+	if vpc != nil {
+		vpa.clientMap[deviceID] = vpc
+	}
+}
+
+func (vpa *VPAgent) getVPClient(deviceID string) intf.IVPClient {
+	if vpc, ok := vpa.clientMap[deviceID]; ok {
+		return vpc
+	}
+	return nil
+}