[VOL-4819] REST Interface for device and ports

Change-Id: I10e136ad5cfe32878fbbca5f897491de721c2fba
diff --git a/internal/pkg/controller/auditdevice.go b/internal/pkg/controller/auditdevice.go
index 33be2e5..2ba8772 100644
--- a/internal/pkg/controller/auditdevice.go
+++ b/internal/pkg/controller/auditdevice.go
@@ -174,7 +174,7 @@
 
 		// Error is ignored as it only drops duplicate ports
 		logger.Infow(ctx, "Calling AddPort", log.Fields{"No": mp.PortNo, "Name": mp.Name})
-		if err := ad.device.AddPort(cntx, mp.PortNo, mp.Name); err != nil {
+		if err := ad.device.AddPort(cntx, mp); err != nil {
 			logger.Warnw(ctx, "AddPort Failed", log.Fields{"No": mp.PortNo, "Name": mp.Name, "Reason": err})
 		}
 		if mp.State == uint32(ofp.OfpPortState_OFPPS_LIVE) {
diff --git a/internal/pkg/controller/changeevent.go b/internal/pkg/controller/changeevent.go
index 46b1be5..9a14d1a 100644
--- a/internal/pkg/controller/changeevent.go
+++ b/internal/pkg/controller/changeevent.go
@@ -74,7 +74,7 @@
 		state := status.PortStatus.Desc.State
 		logger.Infow(ctx, "Process Port Change Event", log.Fields{"Port No": portNo, "Port Name": portName, "State": state, "Reason": status.PortStatus.Reason})
 		if status.PortStatus.Reason == ofp.OfpPortReason_OFPPR_ADD {
-			_ = cet.device.AddPort(ctx, portNo, portName)
+			_ = cet.device.AddPort(ctx, status.PortStatus.Desc)
 			if state == uint32(ofp.OfpPortState_OFPPS_LIVE) {
 				cet.device.ProcessPortState(ctx, portNo, state)
 			}
diff --git a/internal/pkg/controller/controller.go b/internal/pkg/controller/controller.go
index eb48c28..ead1182 100644
--- a/internal/pkg/controller/controller.go
+++ b/internal/pkg/controller/controller.go
@@ -91,7 +91,7 @@
 // AddDevice to add device
 func (v *VoltController) AddDevice(cntx context.Context, config *intf.VPClientCfg) intf.IVPClient {
 
-	d := NewDevice(cntx, config.DeviceID, config.SerialNum, config.VolthaClient, config.SouthBoundID)
+	d := NewDevice(cntx, config.DeviceID, config.SerialNum, config.VolthaClient, config.SouthBoundID, config.MfrDesc, config.HwDesc, config.SwDesc)
 	v.devices[config.DeviceID] = d
 	v.app.AddDevice(cntx, d.ID, d.SerialNum, config.SouthBoundID)
 
diff --git a/internal/pkg/controller/device.go b/internal/pkg/controller/device.go
index d60855a..9fbe172 100644
--- a/internal/pkg/controller/device.go
+++ b/internal/pkg/controller/device.go
@@ -19,8 +19,10 @@
 	"context"
 	"encoding/json"
 	"errors"
+	"fmt"
 	infraerror "voltha-go-controller/internal/pkg/errorcodes"
 	"strconv"
+	"strings"
 	"sync"
 	"time"
 
@@ -53,18 +55,26 @@
 // DevicePort structure
 type DevicePort struct {
 	tasks.Tasks
-	Name    string
-	ID      uint32
-	State   PortState
-	Version string
+	Name      string
+	ID        uint32
+	State     PortState
+	Version   string
+	HwAddr    string
+	CurrSpeed uint32
+	MaxSpeed  uint32
 }
 
 // NewDevicePort is the constructor for DevicePort
-func NewDevicePort(id uint32, name string) *DevicePort {
+func NewDevicePort(mp *ofp.OfpPort) *DevicePort {
 	var port DevicePort
 
-	port.ID = id
-	port.Name = name
+	port.ID = mp.PortNo
+	port.Name = mp.Name
+
+	//port.HwAddr = strings.Trim(strings.Join(strings.Fields(fmt.Sprint("%02x", mp.HwAddr)), ":"), "[]")
+	port.HwAddr = strings.Trim(strings.ReplaceAll(fmt.Sprintf("%02x", mp.HwAddr), " ", ":"), "[]")
+	port.CurrSpeed = mp.CurrSpeed
+	port.MaxSpeed = mp.MaxSpeed
 	port.State = PortStateDown
 	return &port
 }
@@ -127,10 +137,14 @@
 	flowQueue             map[uint32]*UniIDFlowQueue // key is hash ID generated and value is UniIDFlowQueue.
 	deviceAuditInProgress bool
 	SouthBoundID          string
+	MfrDesc               string
+	HwDesc                string
+	SwDesc                string
+	TimeStamp             time.Time
 }
 
 // NewDevice is the constructor for Device
-func NewDevice(cntx context.Context, id string, slno string, vclientHldr *holder.VolthaServiceClientHolder, southBoundID string) *Device {
+func NewDevice(cntx context.Context, id string, slno string, vclientHldr *holder.VolthaServiceClientHolder, southBoundID, mfr, hwDesc, swDesc string) *Device {
 	var device Device
 	device.ID = id
 	device.SerialNum = slno
@@ -143,6 +157,10 @@
 	device.flowQueue = make(map[uint32]*UniIDFlowQueue)
 	//Get the flowhash from db and update the flowhash variable in the device.
 	device.SouthBoundID = southBoundID
+	device.MfrDesc = mfr
+	device.HwDesc = hwDesc
+	device.SwDesc = swDesc
+	device.TimeStamp = time.Now()
 	flowHash, err := db.GetFlowHash(cntx, id)
 	if err != nil {
 		device.flowHash = DefaultMaxFlowQueues
@@ -446,10 +464,11 @@
 
 // AddPort to add the port as requested by the device/VOLTHA
 // Inform the application if the port is successfully added
-func (d *Device) AddPort(cntx context.Context, id uint32, name string) error {
+func (d *Device) AddPort(cntx context.Context, mp *ofp.OfpPort) error {
 	d.portLock.Lock()
 	defer d.portLock.Unlock()
-
+	id := mp.PortNo
+	name := mp.Name
 	if _, ok := d.PortsByID[id]; ok {
 		return errors.New("Duplicate port")
 	}
@@ -457,7 +476,7 @@
 		return errors.New("Duplicate port")
 	}
 
-	p := NewDevicePort(id, name)
+	p := NewDevicePort(mp)
 	d.PortsByID[id] = p
 	d.PortsByName[name] = p
 	d.WritePortToDb(cntx, p)
@@ -631,6 +650,7 @@
 
 	logger.Warnw(ctx, "Device State change Ind: UP", log.Fields{"Device": d.ID})
 	d.State = DeviceStateUP
+	d.TimeStamp = time.Now()
 	GetController().DeviceUpInd(d.ID)
 
 	logger.Warnw(ctx, "Device State change Ind: UP, trigger Audit Tasks", log.Fields{"Device": d.ID})
@@ -667,6 +687,7 @@
 func (d *Device) DeviceUpInd() {
 	logger.Warnw(ctx, "Device State change Ind: UP", log.Fields{"Device": d.ID})
 	d.State = DeviceStateUP
+	d.TimeStamp = time.Now()
 	GetController().DeviceUpInd(d.ID)
 
 	logger.Warnw(ctx, "Device State change Ind: UP, trigger Audit Tasks", log.Fields{"Device": d.ID})
@@ -684,6 +705,7 @@
 func (d *Device) DeviceDownInd() {
 	logger.Warnw(ctx, "Device State change Ind: Down", log.Fields{"Device": d.ID})
 	d.State = DeviceStateDOWN
+	d.TimeStamp = time.Now()
 	GetController().DeviceDownInd(d.ID)
 }
 
@@ -698,6 +720,7 @@
 	}
 
 	d.State = DeviceStateREBOOTED
+	d.TimeStamp = time.Now()
 	GetController().SetRebootInProgressForDevice(d.ID)
 	GetController().DeviceRebootInd(cntx, d.ID, d.SerialNum, d.SouthBoundID)
 	d.ReSetAllPortStates(cntx)
@@ -707,6 +730,7 @@
 func (d *Device) DeviceDisabledInd(cntx context.Context) {
 	logger.Warnw(ctx, "Device State change Ind: Disabled", log.Fields{"Device": d.ID})
 	d.State = DeviceStateDISABLED
+	d.TimeStamp = time.Now()
 	GetController().DeviceDisableInd(cntx, d.ID)
 }
 
diff --git a/internal/pkg/intf/vpagent.go b/internal/pkg/intf/vpagent.go
index 094c58b..3dfbcb2 100644
--- a/internal/pkg/intf/vpagent.go
+++ b/internal/pkg/intf/vpagent.go
@@ -17,6 +17,7 @@
 
 import (
 	"context"
+	"time"
 
 	"voltha-go-controller/internal/pkg/holder"
 
@@ -28,6 +29,10 @@
 	DeviceID         string
 	SerialNum        string
 	SouthBoundID     string
+	MfrDesc          string
+	HwDesc           string
+	SwDesc           string
+	TimeStamp        time.Time
 	VolthaClient     *holder.VolthaServiceClientHolder
 	PacketOutChannel chan *ofp.PacketOut
 }
diff --git a/internal/pkg/vpagent/refresh.go b/internal/pkg/vpagent/refresh.go
index 2761408..71e33ad 100644
--- a/internal/pkg/vpagent/refresh.go
+++ b/internal/pkg/vpagent/refresh.go
@@ -105,15 +105,25 @@
 	vpa.mapLock.Lock()
 	defer vpa.mapLock.Unlock()
 	var serialNum = "Unknown"
+	var mfrDesc = "Unknown"
+	var hwDesc = "Unknown"
+	var swDesc = "Unknown"
 	if device.Desc != nil {
 		serialNum = device.Desc.SerialNum
+		mfrDesc = device.Desc.MfrDesc
+		hwDesc = device.Desc.HwDesc
+		swDesc = device.Desc.SwDesc
 	}
 	vpc := vpa.clientMap[device.Id]
 	if vpc == nil {
 		vpa.VPClientAgent.AddNewDevice(&intf.VPClientCfg{
 			DeviceID:         device.Id,
 			SerialNum:        serialNum,
+			MfrDesc:          mfrDesc,
+			HwDesc:           hwDesc,
+			SwDesc:           swDesc,
 			SouthBoundID:     device.RootDeviceId,
+			TimeStamp:        time.Now(),
 			VolthaClient:     vpa.volthaClient,
 			PacketOutChannel: vpa.packetOutChannel,
 		})