[VOL-4111] Moving Services under the UNI struct
Controlling the UNI state via OMCI Set Messages
Upgraded APIs to reflect the new format

Change-Id: I3a6c166205fad4a381e562ab3b873d03b633303e
diff --git a/internal/common/logger_test.go b/internal/common/logger_test.go
index 6e9de8a..7a04a29 100644
--- a/internal/common/logger_test.go
+++ b/internal/common/logger_test.go
@@ -23,6 +23,10 @@
 	"testing"
 )
 
+func init() {
+	common.SetLogLevel(logrus.StandardLogger(), "error", false)
+}
+
 func Test_SetLogLevel(t *testing.T) {
 	log := logrus.New()
 
diff --git a/internal/common/omci/onu_mib_db.go b/internal/common/omci/onu_mib_db.go
index c8696a7..0b73519 100644
--- a/internal/common/omci/onu_mib_db.go
+++ b/internal/common/omci/onu_mib_db.go
@@ -17,6 +17,7 @@
 package omci
 
 import (
+	"bytes"
 	"encoding/binary"
 	"encoding/hex"
 	me "github.com/opencord/omci-lib-go/generated"
@@ -47,6 +48,23 @@
 	return binary.BigEndian.Uint32(e)
 }
 
+func (e EntityID) FromUint16(id uint16) EntityID {
+	buff := new(bytes.Buffer)
+	err := binary.Write(buff, binary.BigEndian, id)
+	if err != nil {
+		panic(err)
+	}
+
+	return buff.Bytes()
+}
+
+func (e EntityID) Equals(i EntityID) bool {
+	if res := bytes.Compare(e, i); res == 0 {
+		return true
+	}
+	return false
+}
+
 const (
 	cardHolderOnuType byte = 0x01 // ONU is a single piece of integrated equipment
 	ethernetUnitType  byte = 0x2f // Ethernet BASE-T
diff --git a/internal/common/omci/onu_mib_db_test.go b/internal/common/omci/onu_mib_db_test.go
index cea0daf..efb6a1b 100644
--- a/internal/common/omci/onu_mib_db_test.go
+++ b/internal/common/omci/onu_mib_db_test.go
@@ -36,6 +36,23 @@
 	assert.Equal(t, uint16(0), res)
 }
 
+func TestEntityID_FromUint16(t *testing.T) {
+	id := uint16(257)
+	e := EntityID{}.FromUint16(id)
+
+	assert.Equal(t, e.ToString(), "0101")
+	assert.Equal(t, e.ToUint16(), id)
+}
+
+func TestEntityID_Equals(t *testing.T) {
+	a := EntityID{0x01, 0x01}
+	b := EntityID{0x01, 0x01}
+	c := EntityID{0x01, 0x02}
+
+	assert.True(t, a.Equals(b))
+	assert.False(t, a.Equals(c))
+}
+
 func Test_GenerateMibDatabase(t *testing.T) {
 	const uniPortCount = 4
 	mibDb, err := GenerateMibDatabase(uniPortCount)
diff --git a/internal/common/omci/set.go b/internal/common/omci/set.go
index 73e17df..e584b52 100644
--- a/internal/common/omci/set.go
+++ b/internal/common/omci/set.go
@@ -73,3 +73,30 @@
 	return pkt, nil
 
 }
+
+func CreateSetRequest(managedEntity *me.ManagedEntity, tid uint16) ([]byte, error) {
+
+	// TODO
+	// why can't we create the SetRequest as we do for all other omci Requests (eg: MibResetRequest)?
+	// if we do the Attributes are not sent
+
+	request := &omci.SetRequest{
+		MeBasePacket: omci.MeBasePacket{
+			EntityClass:    managedEntity.GetClassID(),
+			EntityInstance: managedEntity.GetEntityID(),
+		},
+		Attributes:    managedEntity.GetAttributeValueMap(),
+		AttributeMask: 0x800, // FIXME how can we generate this based on managedEntity.AttributeValueMap?
+	}
+	omciLogger.Info(request)
+
+	pkt, err := Serialize(omci.SetRequestType, request, tid)
+
+	if err != nil {
+		omciLogger.WithFields(log.Fields{
+			"Err": err,
+		}).Fatalf("Cannot Serialize SetRequest")
+		return nil, err
+	}
+	return HexEncode(pkt)
+}
diff --git a/internal/common/omci/set_test.go b/internal/common/omci/set_test.go
new file mode 100644
index 0000000..33ed35a
--- /dev/null
+++ b/internal/common/omci/set_test.go
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2018-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 omci
+
+import (
+	"github.com/opencord/omci-lib-go"
+	me "github.com/opencord/omci-lib-go/generated"
+	"github.com/stretchr/testify/assert"
+	"testing"
+)
+
+func TestSetRequest(t *testing.T) {
+
+	meId := GenerateUniPortEntityId(1)
+
+	meParams := me.ParamData{
+		EntityID: meId.ToUint16(),
+		Attributes: me.AttributeValueMap{
+			"AdministrativeState": 1,
+		},
+	}
+	meInstance, omciError := me.NewPhysicalPathTerminationPointEthernetUni(meParams)
+	if omciError.GetError() != nil {
+		t.Fatal(omciError.GetError())
+	}
+
+	pkt, err := CreateSetRequest(meInstance, 1)
+	assert.NoError(t, err)
+
+	omciPkt, omciMsg, err := ParseOpenOltOmciPacket(pkt)
+	assert.NoError(t, err)
+	assert.Equal(t, omciMsg.MessageType, omci.SetRequestType)
+
+	msgObj, _ := ParseSetRequest(omciPkt)
+
+	assert.Equal(t, meId.ToUint16(), msgObj.EntityInstance)
+	assert.Equal(t, uint8(1), msgObj.Attributes["AdministrativeState"])
+
+}
diff --git a/internal/common/option_test.go b/internal/common/option_test.go
index 4111ce3..2a57624 100644
--- a/internal/common/option_test.go
+++ b/internal/common/option_test.go
@@ -32,7 +32,7 @@
 	assert.Equal(t, services[0].CTagAllocation, TagAllocationUnique.String())
 	assert.Equal(t, services[0].STagAllocation, TagAllocationShared.String())
 	assert.Equal(t, services[0].NeedsEapol, true)
-	assert.Equal(t, services[0].NeedsDchp, true)
+	assert.Equal(t, services[0].NeedsDhcp, true)
 	assert.Equal(t, services[0].NeedsIgmp, false)
 	assert.Equal(t, services[0].TechnologyProfileID, 64)
 }
diff --git a/internal/common/options.go b/internal/common/options.go
index 6dd7231..545bb5c 100644
--- a/internal/common/options.go
+++ b/internal/common/options.go
@@ -130,7 +130,7 @@
 	CTag                int    `yaml:"c_tag"`
 	STag                int    `yaml:"s_tag"`
 	NeedsEapol          bool   `yaml:"needs_eapol"`
-	NeedsDchp           bool   `yaml:"needs_dhcp"`
+	NeedsDhcp           bool   `yaml:"needs_dhcp"`
 	NeedsIgmp           bool   `yaml:"needs_igmp"`
 	CTagAllocation      string `yaml:"c_tag_allocation"`
 	STagAllocation      string `yaml:"s_tag_allocation"`
@@ -157,7 +157,7 @@
 		str = fmt.Sprintf("%sc_tag_allocation=%s, s_tag_allocation=%s, ",
 			str, s.CTagAllocation, s.STagAllocation)
 		str = fmt.Sprintf("%sneeds_eapol=%t, needs_dhcp=%t, needs_igmp=%t",
-			str, s.NeedsEapol, s.NeedsDchp, s.NeedsIgmp)
+			str, s.NeedsEapol, s.NeedsDhcp, s.NeedsIgmp)
 		str = fmt.Sprintf("%stp_id=%d, uni_tag_match=%d",
 			str, s.TechnologyProfileID, s.UniTagMatch)
 		str = fmt.Sprintf("%s]", str)