[SEBA-884] read config from file

Change-Id: I09c24f5c9504a51d804e68a99a2ac3a02d730573
diff --git a/internal/common/options.go b/internal/common/options.go
index 56acf21..954e66e 100644
--- a/internal/common/options.go
+++ b/internal/common/options.go
@@ -16,69 +16,172 @@
 
 package common
 
-import "flag"
+import (
+	"flag"
+	"fmt"
+	"io/ioutil"
+	"net"
 
-type BBSimCliOptions struct {
-	OltID        int
-	NumNniPerOlt int
-	NumPonPerOlt int
-	NumOnuPerPon int
-	STag         int
-	CTagInit     int
-	Auth         bool
-	Dhcp         bool
-	ProfileCpu   *string
-	LogLevel     string
-	LogCaller    bool
-	Delay        int
-}
+	"gopkg.in/yaml.v2"
+)
 
 type BBRCliOptions struct {
-	*BBSimCliOptions
+	*BBSimYamlConfig
 	BBSimIp      string
 	BBSimPort    string
 	BBSimApiPort string
 	LogFile      string
 }
 
-func GetBBSimOpts() *BBSimCliOptions {
+type BBSimYamlConfig struct {
+	BBSim BBSimConfig
+	Olt   OltConfig
+	BBR   BBRConfig
+}
 
-	olt_id := flag.Int("olt_id", 0, "Number of OLT devices to be emulated")
-	nni := flag.Int("nni", 1, "Number of NNI ports per OLT device to be emulated")
-	pon := flag.Int("pon", 1, "Number of PON ports per OLT device to be emulated")
-	onu := flag.Int("onu", 1, "Number of ONU devices per PON port to be emulated")
+type OltConfig struct {
+	Model              string `yaml:"model"`
+	Vendor             string `yaml:"vendor"`
+	HardwareVersion    string `yaml:"hardware_version"`
+	FirmwareVersion    string `yaml:"firmware_version"`
+	DeviceId           string `yaml:"device_id"`
+	DeviceSerialNumber string `yaml:"device_serial_number"`
+	PonPorts           uint32 `yaml:"pon_ports"`
+	NniPorts           uint32 `yaml:"nni_ports"`
+	OnusPonPort        uint32 `yaml:"onus_per_port"`
+	Technology         string `yaml:"technology"`
+	ID                 int    `yaml:"id"`
+	OltRebootDelay     int    `yaml:"reboot_delay"`
+}
 
-	auth := flag.Bool("auth", false, "Set this flag if you want authentication to start automatically")
-	dhcp := flag.Bool("dhcp", false, "Set this flag if you want DHCP to start automatically")
+type BBSimConfig struct {
+	EnableDhcp           bool    `yaml:"enable_dhcp"`
+	EnableAuth           bool    `yaml:"enable_auth"`
+	LogLevel             string  `yaml:"log_level"`
+	LogCaller            bool    `yaml:"log_caller"`
+	Delay                int     `yaml:"delay"`
+	CpuProfile           *string `yaml:"cpu_profile"`
+	CTagInit             int     `yaml:"c_tag"`
+	STag                 int     `yaml:"s_tag"`
+	OpenOltAddress       string  `yaml:"openolt_address"`
+	ApiAddress           string  `yaml:"api_address"`
+	RestApiAddress       string  `yaml:"rest_api_address"`
+	LegacyApiAddress     string  `yaml:"legacy_api_address"`
+	LegacyRestApiAddress string  `yaml:"legacy_rest_api_address"`
+}
 
-	s_tag := flag.Int("s_tag", 900, "S-Tag value")
-	c_tag_init := flag.Int("c_tag", 900, "C-Tag starting value, each ONU will get a sequential one (targeting 1024 ONUs per BBSim instance the range is big enough)")
+type BBRConfig struct {
+	Log       string `yaml:"log"`
+	LogLevel  string `yaml:"log_level"`
+	LogCaller bool   `yaml:"log_caller"`
+}
+
+var Options *BBSimYamlConfig
+
+func init() {
+	// load settings from config file first
+	Options, _ = LoadBBSimConf("configs/bbsim.yaml")
+}
+
+func getDefaultOps() *BBSimYamlConfig {
+
+	c := &BBSimYamlConfig{
+		BBSimConfig{
+			STag:                 900,
+			CTagInit:             900,
+			EnableDhcp:           false,
+			EnableAuth:           false,
+			LogLevel:             "debug",
+			LogCaller:            false,
+			Delay:                200,
+			OpenOltAddress:       "0.0.0.0:50060",
+			ApiAddress:           "0.0.0.0:50070",
+			RestApiAddress:       "0.0.0.0:50071",
+			LegacyApiAddress:     "0.0.0.0:50072",
+			LegacyRestApiAddress: "0.0.0.0:50073",
+		},
+		OltConfig{
+			Vendor:             "BBSim",
+			Model:              "asfvolt16",
+			HardwareVersion:    "emulated",
+			FirmwareVersion:    "",
+			DeviceSerialNumber: "BBSM00000001",
+			PonPorts:           1,
+			NniPorts:           1,
+			OnusPonPort:        1,
+			Technology:         "XGS-PON",
+			ID:                 0,
+			OltRebootDelay:     10,
+		},
+		BBRConfig{
+			LogLevel:  "debug",
+			LogCaller: false,
+		},
+	}
+	return c
+}
+
+// LoadBBSimConf loads the BBSim configuration from a YAML file
+func LoadBBSimConf(filename string) (*BBSimYamlConfig, error) {
+	yamlConfig := getDefaultOps()
+
+	yamlFile, err := ioutil.ReadFile(filename)
+	if err != nil {
+		fmt.Printf("Cannot load BBSim configuration file: %s. Using defaults.\n", err)
+		return yamlConfig, nil
+	}
+
+	err = yaml.Unmarshal(yamlFile, yamlConfig)
+	if err != nil {
+		fmt.Printf("Error parsing YAML file: %s\n", err)
+	}
+
+	return yamlConfig, nil
+}
+
+// GetBBSimOpts loads the BBSim configuration file and overides options with corresponding CLI flags if set
+func GetBBSimOpts() *BBSimYamlConfig {
+	conf := Options
+
+	olt_id := flag.Int("olt_id", conf.Olt.ID, "OLT device ID")
+	nni := flag.Int("nni", int(conf.Olt.NniPorts), "Number of NNI ports per OLT device to be emulated")
+	pon := flag.Int("pon", int(conf.Olt.PonPorts), "Number of PON ports per OLT device to be emulated")
+	onu := flag.Int("onu", int(conf.Olt.OnusPonPort), "Number of ONU devices per PON port to be emulated")
+
+	s_tag := flag.Int("s_tag", conf.BBSim.STag, "S-Tag initial value")
+	c_tag_init := flag.Int("c_tag", conf.BBSim.CTagInit, "C-Tag starting value, each ONU will get a sequential one (targeting 1024 ONUs per BBSim instance the range is big enough)")
+
+	auth := flag.Bool("auth", conf.BBSim.EnableAuth, "Set this flag if you want authentication to start automatically")
+	dhcp := flag.Bool("dhcp", conf.BBSim.EnableDhcp, "Set this flag if you want DHCP to start automatically")
 
 	profileCpu := flag.String("cpuprofile", "", "write cpu profile to file")
 
-	logLevel := flag.String("logLevel", "debug", "Set the log level (trace, debug, info, warn, error)")
-	logCaller := flag.Bool("logCaller", false, "Whether to print the caller filename or not")
+	logLevel := flag.String("logLevel", conf.BBSim.LogLevel, "Set the log level (trace, debug, info, warn, error)")
+	logCaller := flag.Bool("logCaller", conf.BBSim.LogCaller, "Whether to print the caller filename or not")
 
-	delay := flag.Int("delay", 200, "The delay between ONU DISCOVERY batches in milliseconds (1 ONU per each PON PORT at a time")
+	delay := flag.Int("delay", conf.BBSim.Delay, "The delay between ONU DISCOVERY batches in milliseconds (1 ONU per each PON PORT at a time")
 
 	flag.Parse()
 
-	o := new(BBSimCliOptions)
+	conf.Olt.ID = int(*olt_id)
+	conf.Olt.NniPorts = uint32(*nni)
+	conf.Olt.PonPorts = uint32(*pon)
+	conf.Olt.OnusPonPort = uint32(*onu)
+	conf.BBSim.STag = int(*s_tag)
+	conf.BBSim.CTagInit = int(*c_tag_init)
+	conf.BBSim.CpuProfile = profileCpu
+	conf.BBSim.LogLevel = *logLevel
+	conf.BBSim.LogCaller = *logCaller
+	conf.BBSim.EnableAuth = *auth
+	conf.BBSim.EnableDhcp = *dhcp
+	conf.BBSim.Delay = *delay
 
-	o.OltID = int(*olt_id)
-	o.NumNniPerOlt = int(*nni)
-	o.NumPonPerOlt = int(*pon)
-	o.NumOnuPerPon = int(*onu)
-	o.STag = int(*s_tag)
-	o.CTagInit = int(*c_tag_init)
-	o.ProfileCpu = profileCpu
-	o.LogLevel = *logLevel
-	o.LogCaller = *logCaller
-	o.Auth = *auth
-	o.Dhcp = *dhcp
-	o.Delay = *delay
+	// update device id if not set
+	if conf.Olt.DeviceId == "" {
+		conf.Olt.DeviceId = net.HardwareAddr{0xA, 0xA, 0xA, 0xA, 0xA, byte(conf.Olt.ID)}.String()
+	}
 
-	return o
+	return conf
 }
 
 func GetBBROpts() BBRCliOptions {