blob: 682706800260c1b5bfd15efa9f7ea97cc0fe40f8 [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() {
94 var err error
95
96 if _, err = log.AddPackage(log.JSON, log.WarnLevel, log.Fields{"instanceId": "testing"}); err != nil {
97 log.With(log.Fields{"error": err}).Fatal("Cannot setup logging")
98 }
99 log.UpdateAllLoggers(log.Fields{"instanceId": "testing"})
100 log.SetAllLogLevel(log.ErrorLevel)
101
102 volthaSerialNumberKey = "voltha_serial_number"
103 allDevices = make(map[string]*voltha.Device)
104 allLogicalDevices = make(map[string]*voltha.LogicalDevice)
105
106 grpcHostIP := os.Getenv("DOCKER_HOST_IP")
107 goPath := os.Getenv("GOPATH")
108 if goPath != "" {
109 composePath = fmt.Sprintf("%s/src/github.com/opencord/voltha-go/compose", goPath)
110 } else {
111 composePath = os.Getenv("COMPOSE_PATH")
112 }
113
114 fmt.Println("Using compose path:", composePath)
115
116 //Start the simulated environment
117 if err = tu.StartSimulatedEnv(composePath); err != nil {
118 fmt.Println("Failure starting simulated environment:", err)
119 os.Exit(10)
120 }
121
122 stub, err = tu.SetupGrpcConnectionToCore(grpcHostIP, GRPC_PORT)
123 if err != nil {
124 fmt.Println("Failure connecting to Voltha Core:", err)
125 os.Exit(11)
126 }
127
128 // Wait for the simulated devices to be registered in the Voltha Core
129 adapters := []string{"simulated_olt", "simulated_onu"}
130 if _, err = tu.WaitForAdapterRegistration(stub, adapters, 40); err != nil {
131 fmt.Println("Failure retrieving adapters:", err)
132 os.Exit(12)
133 }
134}
135
136func shutdown() {
137 err := tu.StopSimulatedEnv(composePath)
138 if err != nil {
139 fmt.Println("Failure stop simulated environment:", err)
140 }
141}
142
143func refreshLocalDeviceCache(stub voltha.VolthaServiceClient) error {
144 retrievedDevices, err := tu.ListDevices(stub)
145 if err != nil {
146 return err
147 }
148 for _, d := range retrievedDevices.Items {
149 allDevices[d.Id] = d
150 }
151
152 retrievedLogicalDevices, err := tu.ListLogicalDevices(stub)
153 if err != nil {
154 return err
155 }
156
157 for _, ld := range retrievedLogicalDevices.Items {
158 allLogicalDevices[ld.Id] = ld
159 }
160 return nil
161}
162
163func isPresent(pmName string, pmNames []string) bool {
164 for _, name := range pmNames {
165 if name == pmName {
166 return true
167 }
168 }
169 return false
170}
171
172func verifyDevicePMs(t *testing.T, stub voltha.VolthaServiceClient, device *voltha.Device, allPmNames []string, disabledPmNames []string, frequency uint32) {
173 ui := uuid.New()
174 ctx := metadata.NewOutgoingContext(context.Background(), metadata.Pairs(volthaSerialNumberKey, ui.String()))
175 pmConfigs, err := stub.ListDevicePmConfigs(ctx, &common.ID{Id: device.Id})
176 assert.Nil(t, err)
177 assert.Equal(t, device.Id, pmConfigs.Id)
178 assert.Equal(t, uint32(frequency), pmConfigs.DefaultFreq)
179 assert.Equal(t, false, pmConfigs.FreqOverride)
180 assert.Equal(t, false, pmConfigs.Grouped)
181 assert.Nil(t, pmConfigs.Groups)
182 assert.True(t, len(pmConfigs.Metrics) > 0)
183 metrics := pmConfigs.Metrics
184 for _, m := range metrics {
185 if m.Enabled {
186 assert.True(t, isPresent(m.Name, allPmNames))
187 } else {
188 assert.True(t, isPresent(m.Name, disabledPmNames))
189 }
190 assert.Equal(t, voltha.PmConfig_COUNTER, m.Type)
191 }
192}
193
194func verifyInitialPmConfigs(t *testing.T, stub voltha.VolthaServiceClient) {
195 fmt.Println("Verifying initial PM configs")
196 err := refreshLocalDeviceCache(stub)
197 assert.Nil(t, err)
198 for _, d := range allDevices {
199 if d.Root {
200 verifyDevicePMs(t, stub, d, parentPmNames, []string{}, 150)
201 } else {
202 verifyDevicePMs(t, stub, d, childPmNames, []string{}, 150)
203 }
204 }
205}
206
207func verifyPmFrequencyUpdate(t *testing.T, stub voltha.VolthaServiceClient, device *voltha.Device) {
208 ui := uuid.New()
209 ctx := metadata.NewOutgoingContext(context.Background(), metadata.Pairs(volthaSerialNumberKey, ui.String()))
210 pmConfigs, err := stub.ListDevicePmConfigs(ctx, &common.ID{Id: device.Id})
211 assert.Nil(t, err)
212 pmConfigs.DefaultFreq = 10
213 _, err = stub.UpdateDevicePmConfigs(ctx, pmConfigs)
214 assert.Nil(t, err)
215 if device.Root {
216 verifyDevicePMs(t, stub, device, parentPmNames, []string{}, 10)
217 } else {
218 verifyDevicePMs(t, stub, device, childPmNames, []string{}, 10)
219 }
220}
221
222func updatePmFrequencies(t *testing.T, stub voltha.VolthaServiceClient) {
223 fmt.Println("Verifying update to PMs frequencies")
224 err := refreshLocalDeviceCache(stub)
225 assert.Nil(t, err)
226 for _, d := range allDevices {
227 verifyPmFrequencyUpdate(t, stub, d)
228 }
229}
230
231func verifyDisablingSomePmMetrics(t *testing.T, stub voltha.VolthaServiceClient, device *voltha.Device) {
232 ui := uuid.New()
233 ctx := metadata.NewOutgoingContext(context.Background(), metadata.Pairs(volthaSerialNumberKey, ui.String()))
234 pmConfigs, err := stub.ListDevicePmConfigs(ctx, &common.ID{Id: device.Id})
235 assert.Nil(t, err)
236 metricsToDisable := []string{"tx_64_pkts", "rx_64_pkts", "tx_65_127_pkts", "rx_65_127_pkts"}
237 for _, m := range pmConfigs.Metrics {
238 if isPresent(m.Name, metricsToDisable) {
239 m.Enabled = false
240 }
241 }
242 _, err = stub.UpdateDevicePmConfigs(ctx, pmConfigs)
243 assert.Nil(t, err)
244 if device.Root {
245 verifyDevicePMs(t, stub, device, parentPmNames, metricsToDisable, 10)
246 } else {
247 verifyDevicePMs(t, stub, device, childPmNames, metricsToDisable, 10)
248 }
249}
250
251func disableSomePmMetrics(t *testing.T, stub voltha.VolthaServiceClient) {
252 fmt.Println("Verifying disabling of some PMs")
253 err := refreshLocalDeviceCache(stub)
254 assert.Nil(t, err)
255 for _, d := range allDevices {
256 verifyDisablingSomePmMetrics(t, stub, d)
257 }
258}
259
260func createAndEnableDevices(t *testing.T) {
261 err := tu.SetAllLogLevel(stub, voltha.Logging{Level: common.LogLevel_WARNING})
262 assert.Nil(t, err)
263
264 err = tu.SetLogLevel(stub, voltha.Logging{Level: common.LogLevel_DEBUG, PackageName: "github.com/opencord/voltha-go/rw_core/core"})
265 assert.Nil(t, err)
266
267 startTime := time.Now()
268
269 //Pre-provision the parent device
270 oltDevice, err := tu.PreProvisionDevice(stub)
271 assert.Nil(t, err)
272
273 fmt.Println("Creation of ", NUM_OLTS, " OLT devices took:", time.Since(startTime))
274
275 startTime = time.Now()
276
277 //Enable all parent device - this will enable the child devices as well as validate the child devices
278 err = tu.EnableDevice(stub, oltDevice, NUM_ONUS_PER_OLT)
279 assert.Nil(t, err)
280
281 fmt.Println("Enabling of OLT device took:", time.Since(startTime))
282
283 // Wait until the core and adapters sync up after an enabled
284 time.Sleep(time.Duration(math.Max(10, float64(NUM_OLTS*NUM_ONUS_PER_OLT)/2)) * time.Second)
285
286 err = tu.VerifyDevices(stub, NUM_ONUS_PER_OLT)
287 assert.Nil(t, err)
288
289 lds, err := tu.VerifyLogicalDevices(stub, oltDevice, NUM_ONUS_PER_OLT)
290 assert.Nil(t, err)
291 assert.Equal(t, 1, len(lds.Items))
292}
293
294func TestPerformanceMetrics(t *testing.T) {
295 //1. Test creation and activation of the devices. This will validate the devices as well as the logical device created/
296 createAndEnableDevices(t)
297
298 // 2. Test initial PMs on each device
299 verifyInitialPmConfigs(t, stub)
300
301 // 3. Test frequency update of the pmConfigs
302 updatePmFrequencies(t, stub)
303
304 // 4. Test disable some PM metrics
305 disableSomePmMetrics(t, stub)
306}
307
308func TestMain(m *testing.M) {
309 setup()
310 code := m.Run()
311 shutdown()
312 os.Exit(code)
313}