blob: 60b0bbaf158a5323458001b8404877930dd943cd [file] [log] [blame]
khenaidoob3127472019-07-24 21:04:55 -04001// +build integration
2
3/*
4 * Copyright 2018-present Open Networking Foundation
5
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9
10 * http://www.apache.org/licenses/LICENSE-2.0
11
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18package core
19
20import (
21 "context"
22 "fmt"
23 "github.com/google/uuid"
khenaidoob3127472019-07-24 21:04:55 -040024 tu "github.com/opencord/voltha-go/tests/utils"
serkant.uluderya2ae470f2020-01-21 11:13:09 -080025 "github.com/opencord/voltha-lib-go/v3/pkg/log"
26 "github.com/opencord/voltha-protos/v3/go/common"
27 "github.com/opencord/voltha-protos/v3/go/voltha"
khenaidoob3127472019-07-24 21:04:55 -040028 "github.com/stretchr/testify/assert"
29 "google.golang.org/grpc/metadata"
30 "math"
31 "os"
32 "testing"
33 "time"
34)
35
36var stub voltha.VolthaServiceClient
37var volthaSerialNumberKey string
38
39/*
40 This local "integration" test uses one RW-Core, one simulated_olt and one simulated_onu adapter to test performance
41metrics, in a development environment. It uses docker-compose to set up the local environment. However, it can
42easily be extended to run in k8s environment.
43
44The compose files used are located under %GOPATH/src/github.com/opencord/voltha-go/compose. If the GOPATH is not set
45then you can specify the location of the compose files by using COMPOSE_PATH to set the compose files location.
46
47To run this test: DOCKER_HOST_IP=<local IP> go test -v
48
49*/
50
51var allDevices map[string]*voltha.Device
52var allLogicalDevices map[string]*voltha.LogicalDevice
53
54var composePath string
55
56const (
57 GRPC_PORT = 50057
58 NUM_OLTS = 1
59 NUM_ONUS_PER_OLT = 4 // This should coincide with the number of onus per olt in adapters-simulated.yml file
60)
61
62var parentPmNames = []string{
63 "tx_64_pkts",
64 "tx_65_127_pkts",
65 "tx_128_255_pkts",
66 "tx_256_511_pkts",
67 "tx_512_1023_pkts",
68 "tx_1024_1518_pkts",
69 "tx_1519_9k_pkts",
70 "rx_64_pkts",
71 "rx_65_127_pkts",
72 "rx_128_255_pkts",
73 "rx_256_511_pkts",
74 "rx_512_1023_pkts",
75 "rx_1024_1518_pkts",
76 "rx_1519_9k_pkts",
77}
78
79var childPmNames = []string{
80 "tx_64_pkts",
81 "tx_65_127_pkts",
82 "tx_128_255_pkts",
83 "tx_1024_1518_pkts",
84 "tx_1519_9k_pkts",
85 "rx_64_pkts",
86 "rx_64_pkts",
87 "rx_65_127_pkts",
88 "rx_128_255_pkts",
89 "rx_1024_1518_pkts",
90 "rx_1519_9k_pkts",
91}
92
93func setup() {
khenaidoob3127472019-07-24 21:04:55 -040094 volthaSerialNumberKey = "voltha_serial_number"
95 allDevices = make(map[string]*voltha.Device)
96 allLogicalDevices = make(map[string]*voltha.LogicalDevice)
97
98 grpcHostIP := os.Getenv("DOCKER_HOST_IP")
99 goPath := os.Getenv("GOPATH")
100 if goPath != "" {
101 composePath = fmt.Sprintf("%s/src/github.com/opencord/voltha-go/compose", goPath)
102 } else {
103 composePath = os.Getenv("COMPOSE_PATH")
104 }
105
106 fmt.Println("Using compose path:", composePath)
107
108 //Start the simulated environment
109 if err = tu.StartSimulatedEnv(composePath); err != nil {
110 fmt.Println("Failure starting simulated environment:", err)
111 os.Exit(10)
112 }
113
114 stub, err = tu.SetupGrpcConnectionToCore(grpcHostIP, GRPC_PORT)
115 if err != nil {
116 fmt.Println("Failure connecting to Voltha Core:", err)
117 os.Exit(11)
118 }
119
120 // Wait for the simulated devices to be registered in the Voltha Core
121 adapters := []string{"simulated_olt", "simulated_onu"}
122 if _, err = tu.WaitForAdapterRegistration(stub, adapters, 40); err != nil {
123 fmt.Println("Failure retrieving adapters:", err)
124 os.Exit(12)
125 }
126}
127
128func shutdown() {
129 err := tu.StopSimulatedEnv(composePath)
130 if err != nil {
131 fmt.Println("Failure stop simulated environment:", err)
132 }
133}
134
135func refreshLocalDeviceCache(stub voltha.VolthaServiceClient) error {
136 retrievedDevices, err := tu.ListDevices(stub)
137 if err != nil {
138 return err
139 }
140 for _, d := range retrievedDevices.Items {
141 allDevices[d.Id] = d
142 }
143
144 retrievedLogicalDevices, err := tu.ListLogicalDevices(stub)
145 if err != nil {
146 return err
147 }
148
149 for _, ld := range retrievedLogicalDevices.Items {
150 allLogicalDevices[ld.Id] = ld
151 }
152 return nil
153}
154
155func isPresent(pmName string, pmNames []string) bool {
156 for _, name := range pmNames {
157 if name == pmName {
158 return true
159 }
160 }
161 return false
162}
163
164func verifyDevicePMs(t *testing.T, stub voltha.VolthaServiceClient, device *voltha.Device, allPmNames []string, disabledPmNames []string, frequency uint32) {
165 ui := uuid.New()
166 ctx := metadata.NewOutgoingContext(context.Background(), metadata.Pairs(volthaSerialNumberKey, ui.String()))
167 pmConfigs, err := stub.ListDevicePmConfigs(ctx, &common.ID{Id: device.Id})
168 assert.Nil(t, err)
169 assert.Equal(t, device.Id, pmConfigs.Id)
170 assert.Equal(t, uint32(frequency), pmConfigs.DefaultFreq)
171 assert.Equal(t, false, pmConfigs.FreqOverride)
172 assert.Equal(t, false, pmConfigs.Grouped)
173 assert.Nil(t, pmConfigs.Groups)
174 assert.True(t, len(pmConfigs.Metrics) > 0)
175 metrics := pmConfigs.Metrics
176 for _, m := range metrics {
177 if m.Enabled {
178 assert.True(t, isPresent(m.Name, allPmNames))
179 } else {
180 assert.True(t, isPresent(m.Name, disabledPmNames))
181 }
182 assert.Equal(t, voltha.PmConfig_COUNTER, m.Type)
183 }
184}
185
186func verifyInitialPmConfigs(t *testing.T, stub voltha.VolthaServiceClient) {
187 fmt.Println("Verifying initial PM configs")
188 err := refreshLocalDeviceCache(stub)
189 assert.Nil(t, err)
190 for _, d := range allDevices {
191 if d.Root {
192 verifyDevicePMs(t, stub, d, parentPmNames, []string{}, 150)
193 } else {
194 verifyDevicePMs(t, stub, d, childPmNames, []string{}, 150)
195 }
196 }
197}
198
199func verifyPmFrequencyUpdate(t *testing.T, stub voltha.VolthaServiceClient, device *voltha.Device) {
200 ui := uuid.New()
201 ctx := metadata.NewOutgoingContext(context.Background(), metadata.Pairs(volthaSerialNumberKey, ui.String()))
202 pmConfigs, err := stub.ListDevicePmConfigs(ctx, &common.ID{Id: device.Id})
203 assert.Nil(t, err)
204 pmConfigs.DefaultFreq = 10
205 _, err = stub.UpdateDevicePmConfigs(ctx, pmConfigs)
206 assert.Nil(t, err)
207 if device.Root {
208 verifyDevicePMs(t, stub, device, parentPmNames, []string{}, 10)
209 } else {
210 verifyDevicePMs(t, stub, device, childPmNames, []string{}, 10)
211 }
212}
213
214func updatePmFrequencies(t *testing.T, stub voltha.VolthaServiceClient) {
215 fmt.Println("Verifying update to PMs frequencies")
216 err := refreshLocalDeviceCache(stub)
217 assert.Nil(t, err)
218 for _, d := range allDevices {
219 verifyPmFrequencyUpdate(t, stub, d)
220 }
221}
222
223func verifyDisablingSomePmMetrics(t *testing.T, stub voltha.VolthaServiceClient, device *voltha.Device) {
224 ui := uuid.New()
225 ctx := metadata.NewOutgoingContext(context.Background(), metadata.Pairs(volthaSerialNumberKey, ui.String()))
226 pmConfigs, err := stub.ListDevicePmConfigs(ctx, &common.ID{Id: device.Id})
227 assert.Nil(t, err)
228 metricsToDisable := []string{"tx_64_pkts", "rx_64_pkts", "tx_65_127_pkts", "rx_65_127_pkts"}
229 for _, m := range pmConfigs.Metrics {
230 if isPresent(m.Name, metricsToDisable) {
231 m.Enabled = false
232 }
233 }
234 _, err = stub.UpdateDevicePmConfigs(ctx, pmConfigs)
235 assert.Nil(t, err)
236 if device.Root {
237 verifyDevicePMs(t, stub, device, parentPmNames, metricsToDisable, 10)
238 } else {
239 verifyDevicePMs(t, stub, device, childPmNames, metricsToDisable, 10)
240 }
241}
242
243func disableSomePmMetrics(t *testing.T, stub voltha.VolthaServiceClient) {
244 fmt.Println("Verifying disabling of some PMs")
245 err := refreshLocalDeviceCache(stub)
246 assert.Nil(t, err)
247 for _, d := range allDevices {
248 verifyDisablingSomePmMetrics(t, stub, d)
249 }
250}
251
252func createAndEnableDevices(t *testing.T) {
253 err := tu.SetAllLogLevel(stub, voltha.Logging{Level: common.LogLevel_WARNING})
254 assert.Nil(t, err)
255
256 err = tu.SetLogLevel(stub, voltha.Logging{Level: common.LogLevel_DEBUG, PackageName: "github.com/opencord/voltha-go/rw_core/core"})
257 assert.Nil(t, err)
258
259 startTime := time.Now()
260
261 //Pre-provision the parent device
262 oltDevice, err := tu.PreProvisionDevice(stub)
263 assert.Nil(t, err)
264
265 fmt.Println("Creation of ", NUM_OLTS, " OLT devices took:", time.Since(startTime))
266
267 startTime = time.Now()
268
269 //Enable all parent device - this will enable the child devices as well as validate the child devices
270 err = tu.EnableDevice(stub, oltDevice, NUM_ONUS_PER_OLT)
271 assert.Nil(t, err)
272
273 fmt.Println("Enabling of OLT device took:", time.Since(startTime))
274
275 // Wait until the core and adapters sync up after an enabled
276 time.Sleep(time.Duration(math.Max(10, float64(NUM_OLTS*NUM_ONUS_PER_OLT)/2)) * time.Second)
277
278 err = tu.VerifyDevices(stub, NUM_ONUS_PER_OLT)
279 assert.Nil(t, err)
280
281 lds, err := tu.VerifyLogicalDevices(stub, oltDevice, NUM_ONUS_PER_OLT)
282 assert.Nil(t, err)
283 assert.Equal(t, 1, len(lds.Items))
284}
285
286func TestPerformanceMetrics(t *testing.T) {
287 //1. Test creation and activation of the devices. This will validate the devices as well as the logical device created/
288 createAndEnableDevices(t)
289
290 // 2. Test initial PMs on each device
291 verifyInitialPmConfigs(t, stub)
292
293 // 3. Test frequency update of the pmConfigs
294 updatePmFrequencies(t, stub)
295
296 // 4. Test disable some PM metrics
297 disableSomePmMetrics(t, stub)
298}
299
300func TestMain(m *testing.M) {
301 setup()
302 code := m.Run()
303 shutdown()
304 os.Exit(code)
305}