@@ -29,11 +29,15 @@ import (
29
29
"syscall"
30
30
"strings"
31
31
"flag"
32
+ "github.com/go-redis/redis"
32
33
log "github.com/golang/glog"
33
34
)
34
35
35
36
var CVL_SCHEMA string = "/usr/sbin/schema/"
36
37
var CVL_CFG_FILE string = "/usr/sbin/cvl_cfg.json"
38
+ const SONIC_DB_CONFIG_FILE string = "/var/run/redis/sonic-db/database_config.json"
39
+ const ENV_VAR_SONIC_DB_CONFIG_FILE = "DB_CONFIG_PATH"
40
+ var sonic_db_config = make (map [string ]interface {})
37
41
38
42
//package init function
39
43
func init () {
@@ -44,6 +48,9 @@ func init() {
44
48
if (os .Getenv ("CVL_CFG_FILE" ) != "" ) {
45
49
CVL_CFG_FILE = os .Getenv ("CVL_CFG_FILE" )
46
50
}
51
+
52
+ //Initialize DB settings
53
+ dbCfgInit ()
47
54
}
48
55
49
56
var cvlCfgMap map [string ]string
@@ -253,3 +260,184 @@ func SkipSemanticValidation() bool {
253
260
254
261
return false
255
262
}
263
+
264
+ //Function to read Redis DB configuration from file.
265
+ //In absence of the file, it uses default config for CONFIG_DB
266
+ //so that CVL UT will pass in development environment.
267
+ func dbCfgInit () {
268
+ defaultDBConfig := `{
269
+ "INSTANCES": {
270
+ "redis":{
271
+ "hostname" : "127.0.0.1",
272
+ "port" : 6379
273
+ }
274
+ },
275
+ "DATABASES" : {
276
+ "CONFIG_DB" : {
277
+ "id" : 4,
278
+ "separator": "|",
279
+ "instance" : "redis"
280
+ },
281
+ "STATE_DB" : {
282
+ "id" : 6,
283
+ "separator": "|",
284
+ "instance" : "redis"
285
+ }
286
+ }
287
+ }`
288
+
289
+ dbCfgFile := ""
290
+
291
+ //Check if multi-db config file is present
292
+ if _ , errF := os .Stat (SONIC_DB_CONFIG_FILE ); ! os .IsNotExist (errF ) {
293
+ dbCfgFile = SONIC_DB_CONFIG_FILE
294
+ } else {
295
+ //Check if multi-db config file is specified in environment
296
+ if fileName := os .Getenv (ENV_VAR_SONIC_DB_CONFIG_FILE ); fileName != "" {
297
+ if _ , errF := os .Stat (fileName ); ! os .IsNotExist (errF ) {
298
+ dbCfgFile = fileName
299
+ }
300
+ }
301
+ }
302
+
303
+ if dbCfgFile != "" {
304
+ //Read from multi-db config file
305
+ data , err := ioutil .ReadFile (dbCfgFile )
306
+ if err != nil {
307
+ panic (err )
308
+ } else {
309
+ err = json .Unmarshal ([]byte (data ), & sonic_db_config )
310
+ if err != nil {
311
+ panic (err )
312
+ }
313
+ }
314
+ } else {
315
+ //No multi-db config file is present.
316
+ //Use default config for CONFIG_DB setting, this avoids CVL UT failure
317
+ //in absence of at multi-db config file
318
+ err := json .Unmarshal ([]byte (defaultDBConfig ), & sonic_db_config )
319
+ if err != nil {
320
+ panic (err )
321
+ }
322
+ }
323
+ }
324
+
325
+ //Get list of DB
326
+ func getDbList ()(map [string ]interface {}) {
327
+ db_list , ok := sonic_db_config ["DATABASES" ].(map [string ]interface {})
328
+ if ! ok {
329
+ panic (fmt .Errorf ("DATABASES' is not valid key in %s!" ,
330
+ SONIC_DB_CONFIG_FILE ))
331
+ }
332
+ return db_list
333
+ }
334
+
335
+ //Get DB instance based on given DB name
336
+ func getDbInst (dbName string )(map [string ]interface {}) {
337
+ db , ok := sonic_db_config ["DATABASES" ].(map [string ]interface {})[dbName ]
338
+ if ! ok {
339
+ panic (fmt .Errorf ("database name '%v' is not valid in %s !" ,
340
+ dbName , SONIC_DB_CONFIG_FILE ))
341
+ }
342
+ inst_name , ok := db .(map [string ]interface {})["instance" ]
343
+ if ! ok {
344
+ panic (fmt .Errorf ("'instance' is not a valid field in %s !" ,
345
+ SONIC_DB_CONFIG_FILE ))
346
+ }
347
+ inst , ok := sonic_db_config ["INSTANCES" ].(map [string ]interface {})[inst_name .(string )]
348
+ if ! ok {
349
+ panic (fmt .Errorf ("instance name '%v' is not valid in %s !" ,
350
+ inst_name , SONIC_DB_CONFIG_FILE ))
351
+ }
352
+ return inst .(map [string ]interface {})
353
+ }
354
+
355
+ //GetDbSeparator Get DB separator based on given DB name
356
+ func GetDbSeparator (dbName string )(string ) {
357
+ db_list := getDbList ()
358
+ separator , ok := db_list [dbName ].(map [string ]interface {})["separator" ]
359
+ if ! ok {
360
+ panic (fmt .Errorf ("'separator' is not a valid field in %s !" ,
361
+ SONIC_DB_CONFIG_FILE ))
362
+ }
363
+ return separator .(string )
364
+ }
365
+
366
+ //GetDbId Get DB id on given db name
367
+ func GetDbId (dbName string )(int ) {
368
+ db_list := getDbList ()
369
+ id , ok := db_list [dbName ].(map [string ]interface {})["id" ]
370
+ if ! ok {
371
+ panic (fmt .Errorf ("'id' is not a valid field in %s !" ,
372
+ SONIC_DB_CONFIG_FILE ))
373
+ }
374
+ return int (id .(float64 ))
375
+ }
376
+
377
+ //GetDbSock Get DB socket path
378
+ func GetDbSock (dbName string )(string ) {
379
+ inst := getDbInst (dbName )
380
+ unix_socket_path , ok := inst ["unix_socket_path" ]
381
+ if ! ok {
382
+ CVL_LEVEL_LOG (INFO , "'unix_socket_path' is not " +
383
+ "a valid field in %s !" , SONIC_DB_CONFIG_FILE )
384
+
385
+ return ""
386
+ }
387
+
388
+ return unix_socket_path .(string )
389
+ }
390
+
391
+ //GetDbTcpAddr Get DB TCP endpoint
392
+ func GetDbTcpAddr (dbName string )(string ) {
393
+ inst := getDbInst (dbName )
394
+ hostname , ok := inst ["hostname" ]
395
+ if ! ok {
396
+ panic (fmt .Errorf ("'hostname' is not a valid field in %s !" ,
397
+ SONIC_DB_CONFIG_FILE ))
398
+ }
399
+
400
+ port , ok1 := inst ["port" ]
401
+ if ! ok1 {
402
+ panic (fmt .Errorf ("'port' is not a valid field in %s !" ,
403
+ SONIC_DB_CONFIG_FILE ))
404
+ }
405
+
406
+ return fmt .Sprintf ("%v:%v" , hostname , port )
407
+ }
408
+
409
+ //NewDbClient Get new redis client
410
+ func NewDbClient (dbName string ) * redis.Client {
411
+ var redisClient * redis.Client = nil
412
+
413
+ //Try unix domain socket first
414
+ if dbSock := GetDbSock (dbName ); dbSock != "" {
415
+ redisClient = redis .NewClient (& redis.Options {
416
+ Network : "unix" ,
417
+ Addr : dbSock ,
418
+ Password : "" ,
419
+ DB : GetDbId (dbName ),
420
+ })
421
+ } else {
422
+ //Otherwise, use TCP socket
423
+ redisClient = redis .NewClient (& redis.Options {
424
+ Network : "tcp" ,
425
+ Addr : GetDbTcpAddr (dbName ),
426
+ Password : "" ,
427
+ DB : GetDbId (dbName ),
428
+ })
429
+ }
430
+
431
+ if (redisClient == nil ) {
432
+ return nil
433
+ }
434
+
435
+ //Check the connectivity
436
+ _ , err := redisClient .Ping ().Result ()
437
+ if err != nil {
438
+ CVL_LEVEL_LOG (ERROR , "Failed to connect to Redis server %v" , err )
439
+ return nil
440
+ }
441
+
442
+ return redisClient
443
+ }
0 commit comments