blob: 60b0bbaf158a5323458001b8404877930dd943cd [file] [log] [blame]
// +build integration
/*
* 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 core
import (
"context"
"fmt"
"github.com/google/uuid"
tu "github.com/opencord/voltha-go/tests/utils"
"github.com/opencord/voltha-lib-go/v3/pkg/log"
"github.com/opencord/voltha-protos/v3/go/common"
"github.com/opencord/voltha-protos/v3/go/voltha"
"github.com/stretchr/testify/assert"
"google.golang.org/grpc/metadata"
"math"
"os"
"testing"
"time"
)
var stub voltha.VolthaServiceClient
var volthaSerialNumberKey string
/*
This local "integration" test uses one RW-Core, one simulated_olt and one simulated_onu adapter to test performance
metrics, in a development environment. It uses docker-compose to set up the local environment. However, it can
easily be extended to run in k8s environment.
The compose files used are located under %GOPATH/src/github.com/opencord/voltha-go/compose. If the GOPATH is not set
then you can specify the location of the compose files by using COMPOSE_PATH to set the compose files location.
To run this test: DOCKER_HOST_IP=<local IP> go test -v
*/
var allDevices map[string]*voltha.Device
var allLogicalDevices map[string]*voltha.LogicalDevice
var composePath string
const (
GRPC_PORT = 50057
NUM_OLTS = 1
NUM_ONUS_PER_OLT = 4 // This should coincide with the number of onus per olt in adapters-simulated.yml file
)
var parentPmNames = []string{
"tx_64_pkts",
"tx_65_127_pkts",
"tx_128_255_pkts",
"tx_256_511_pkts",
"tx_512_1023_pkts",
"tx_1024_1518_pkts",
"tx_1519_9k_pkts",
"rx_64_pkts",
"rx_65_127_pkts",
"rx_128_255_pkts",
"rx_256_511_pkts",
"rx_512_1023_pkts",
"rx_1024_1518_pkts",
"rx_1519_9k_pkts",
}
var childPmNames = []string{
"tx_64_pkts",
"tx_65_127_pkts",
"tx_128_255_pkts",
"tx_1024_1518_pkts",
"tx_1519_9k_pkts",
"rx_64_pkts",
"rx_64_pkts",
"rx_65_127_pkts",
"rx_128_255_pkts",
"rx_1024_1518_pkts",
"rx_1519_9k_pkts",
}
func setup() {
volthaSerialNumberKey = "voltha_serial_number"
allDevices = make(map[string]*voltha.Device)
allLogicalDevices = make(map[string]*voltha.LogicalDevice)
grpcHostIP := os.Getenv("DOCKER_HOST_IP")
goPath := os.Getenv("GOPATH")
if goPath != "" {
composePath = fmt.Sprintf("%s/src/github.com/opencord/voltha-go/compose", goPath)
} else {
composePath = os.Getenv("COMPOSE_PATH")
}
fmt.Println("Using compose path:", composePath)
//Start the simulated environment
if err = tu.StartSimulatedEnv(composePath); err != nil {
fmt.Println("Failure starting simulated environment:", err)
os.Exit(10)
}
stub, err = tu.SetupGrpcConnectionToCore(grpcHostIP, GRPC_PORT)
if err != nil {
fmt.Println("Failure connecting to Voltha Core:", err)
os.Exit(11)
}
// Wait for the simulated devices to be registered in the Voltha Core
adapters := []string{"simulated_olt", "simulated_onu"}
if _, err = tu.WaitForAdapterRegistration(stub, adapters, 40); err != nil {
fmt.Println("Failure retrieving adapters:", err)
os.Exit(12)
}
}
func shutdown() {
err := tu.StopSimulatedEnv(composePath)
if err != nil {
fmt.Println("Failure stop simulated environment:", err)
}
}
func refreshLocalDeviceCache(stub voltha.VolthaServiceClient) error {
retrievedDevices, err := tu.ListDevices(stub)
if err != nil {
return err
}
for _, d := range retrievedDevices.Items {
allDevices[d.Id] = d
}
retrievedLogicalDevices, err := tu.ListLogicalDevices(stub)
if err != nil {
return err
}
for _, ld := range retrievedLogicalDevices.Items {
allLogicalDevices[ld.Id] = ld
}
return nil
}
func isPresent(pmName string, pmNames []string) bool {
for _, name := range pmNames {
if name == pmName {
return true
}
}
return false
}
func verifyDevicePMs(t *testing.T, stub voltha.VolthaServiceClient, device *voltha.Device, allPmNames []string, disabledPmNames []string, frequency uint32) {
ui := uuid.New()
ctx := metadata.NewOutgoingContext(context.Background(), metadata.Pairs(volthaSerialNumberKey, ui.String()))
pmConfigs, err := stub.ListDevicePmConfigs(ctx, &common.ID{Id: device.Id})
assert.Nil(t, err)
assert.Equal(t, device.Id, pmConfigs.Id)
assert.Equal(t, uint32(frequency), pmConfigs.DefaultFreq)
assert.Equal(t, false, pmConfigs.FreqOverride)
assert.Equal(t, false, pmConfigs.Grouped)
assert.Nil(t, pmConfigs.Groups)
assert.True(t, len(pmConfigs.Metrics) > 0)
metrics := pmConfigs.Metrics
for _, m := range metrics {
if m.Enabled {
assert.True(t, isPresent(m.Name, allPmNames))
} else {
assert.True(t, isPresent(m.Name, disabledPmNames))
}
assert.Equal(t, voltha.PmConfig_COUNTER, m.Type)
}
}
func verifyInitialPmConfigs(t *testing.T, stub voltha.VolthaServiceClient) {
fmt.Println("Verifying initial PM configs")
err := refreshLocalDeviceCache(stub)
assert.Nil(t, err)
for _, d := range allDevices {
if d.Root {
verifyDevicePMs(t, stub, d, parentPmNames, []string{}, 150)
} else {
verifyDevicePMs(t, stub, d, childPmNames, []string{}, 150)
}
}
}
func verifyPmFrequencyUpdate(t *testing.T, stub voltha.VolthaServiceClient, device *voltha.Device) {
ui := uuid.New()
ctx := metadata.NewOutgoingContext(context.Background(), metadata.Pairs(volthaSerialNumberKey, ui.String()))
pmConfigs, err := stub.ListDevicePmConfigs(ctx, &common.ID{Id: device.Id})
assert.Nil(t, err)
pmConfigs.DefaultFreq = 10
_, err = stub.UpdateDevicePmConfigs(ctx, pmConfigs)
assert.Nil(t, err)
if device.Root {
verifyDevicePMs(t, stub, device, parentPmNames, []string{}, 10)
} else {
verifyDevicePMs(t, stub, device, childPmNames, []string{}, 10)
}
}
func updatePmFrequencies(t *testing.T, stub voltha.VolthaServiceClient) {
fmt.Println("Verifying update to PMs frequencies")
err := refreshLocalDeviceCache(stub)
assert.Nil(t, err)
for _, d := range allDevices {
verifyPmFrequencyUpdate(t, stub, d)
}
}
func verifyDisablingSomePmMetrics(t *testing.T, stub voltha.VolthaServiceClient, device *voltha.Device) {
ui := uuid.New()
ctx := metadata.NewOutgoingContext(context.Background(), metadata.Pairs(volthaSerialNumberKey, ui.String()))
pmConfigs, err := stub.ListDevicePmConfigs(ctx, &common.ID{Id: device.Id})
assert.Nil(t, err)
metricsToDisable := []string{"tx_64_pkts", "rx_64_pkts", "tx_65_127_pkts", "rx_65_127_pkts"}
for _, m := range pmConfigs.Metrics {
if isPresent(m.Name, metricsToDisable) {
m.Enabled = false
}
}
_, err = stub.UpdateDevicePmConfigs(ctx, pmConfigs)
assert.Nil(t, err)
if device.Root {
verifyDevicePMs(t, stub, device, parentPmNames, metricsToDisable, 10)
} else {
verifyDevicePMs(t, stub, device, childPmNames, metricsToDisable, 10)
}
}
func disableSomePmMetrics(t *testing.T, stub voltha.VolthaServiceClient) {
fmt.Println("Verifying disabling of some PMs")
err := refreshLocalDeviceCache(stub)
assert.Nil(t, err)
for _, d := range allDevices {
verifyDisablingSomePmMetrics(t, stub, d)
}
}
func createAndEnableDevices(t *testing.T) {
err := tu.SetAllLogLevel(stub, voltha.Logging{Level: common.LogLevel_WARNING})
assert.Nil(t, err)
err = tu.SetLogLevel(stub, voltha.Logging{Level: common.LogLevel_DEBUG, PackageName: "github.com/opencord/voltha-go/rw_core/core"})
assert.Nil(t, err)
startTime := time.Now()
//Pre-provision the parent device
oltDevice, err := tu.PreProvisionDevice(stub)
assert.Nil(t, err)
fmt.Println("Creation of ", NUM_OLTS, " OLT devices took:", time.Since(startTime))
startTime = time.Now()
//Enable all parent device - this will enable the child devices as well as validate the child devices
err = tu.EnableDevice(stub, oltDevice, NUM_ONUS_PER_OLT)
assert.Nil(t, err)
fmt.Println("Enabling of OLT device took:", time.Since(startTime))
// Wait until the core and adapters sync up after an enabled
time.Sleep(time.Duration(math.Max(10, float64(NUM_OLTS*NUM_ONUS_PER_OLT)/2)) * time.Second)
err = tu.VerifyDevices(stub, NUM_ONUS_PER_OLT)
assert.Nil(t, err)
lds, err := tu.VerifyLogicalDevices(stub, oltDevice, NUM_ONUS_PER_OLT)
assert.Nil(t, err)
assert.Equal(t, 1, len(lds.Items))
}
func TestPerformanceMetrics(t *testing.T) {
//1. Test creation and activation of the devices. This will validate the devices as well as the logical device created/
createAndEnableDevices(t)
// 2. Test initial PMs on each device
verifyInitialPmConfigs(t, stub)
// 3. Test frequency update of the pmConfigs
updatePmFrequencies(t, stub)
// 4. Test disable some PM metrics
disableSomePmMetrics(t, stub)
}
func TestMain(m *testing.M) {
setup()
code := m.Run()
shutdown()
os.Exit(code)
}