X-Git-Url: https://gerrit.o-ran-sc.org/r/gitweb?a=blobdiff_plain;f=cmd%2Fvesmgr%2Fconfig.go;h=b79d19be7a9d90c08aea90768dad934f80c094ca;hb=refs%2Fchanges%2F05%2F4905%2F3;hp=e2c9f25cb5bf297daae8985afda9e9f8a6f8ba8a;hpb=412df96a23a30a82d2a031556888aeaf9604ada8;p=ric-plt%2Fvespamgr.git diff --git a/cmd/vesmgr/config.go b/cmd/vesmgr/config.go old mode 100644 new mode 100755 index e2c9f25..b79d19b --- a/cmd/vesmgr/config.go +++ b/cmd/vesmgr/config.go @@ -13,42 +13,72 @@ * 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. + * + * This source code is part of the near-RT RIC (RAN Intelligent Controller) + * platform project (RICP). + * */ package main import ( "encoding/json" - "gopkg.in/yaml.v2" + "fmt" "io" + "io/ioutil" "os" "strconv" + "strings" "time" + + "gopkg.in/yaml.v2" ) +const defaultReportingEntityID = "00000000-0000-0000-0000-000000000000" +const defaultVNFName = "Vespa" +const defaultNFNamingCode = "ricp" + +func readSystemUUID() string { + data, err := ioutil.ReadFile("/sys/class/dmi/id/product_uuid") + if err != nil { + return defaultReportingEntityID + } + return strings.TrimSpace(string(data)) +} + +func getVNFName() string { + VNFName := os.Getenv("VESMGR_VNFNAME") + if VNFName == "" { + return defaultVNFName + } + return VNFName +} + +func getNFNamingCode() string { + NFNamingCode := os.Getenv("VESMGR_NFNAMINGCODE") + if NFNamingCode == "" { + return defaultNFNamingCode + } + return NFNamingCode +} + func basicVespaConf() VESAgentConfiguration { var vespaconf = VESAgentConfiguration{ DataDir: "/tmp/data", Debug: false, Event: EventConfiguration{ - VNFName: "vespa-demo", // XXX - ReportingEntityID: "1af5bfa9-40b4-4522-b045-40e54f0310f", // XXX - MaxSize: 2000000, - NfNamingCode: "hsxp", - NfcNamingCodes: []NfcNamingCode{ - NfcNamingCode{ - Type: "oam", - Vnfcs: []string{"lr-ope-0", "lr-ope-1", "lr-ope-2"}, - }, - NfcNamingCode{ - Type: "etl", - Vnfcs: []string{"lr-pro-0", "lr-pro-1"}, - }, - }, - RetryInterval: time.Second * 5, - MaxMissed: 2, + VNFName: getVNFName(), + ReportingEntityName: "Vespa", + ReportingEntityID: readSystemUUID(), + MaxSize: 2000000, + NfNamingCode: getNFNamingCode(), + NfcNamingCodes: []NfcNamingCode{}, + RetryInterval: time.Second * 5, + MaxMissed: 2, }, Measurement: MeasurementConfiguration{ + // Domain abbreviation has to be set to “Mvfs” for VES 5.3, + // and to “Measurement” for later VES interface versions. DomainAbbreviation: "Mvfs", MaxBufferingDuration: time.Hour, Prometheus: PrometheusConfig{ @@ -65,12 +95,18 @@ func basicVespaConf() VESAgentConfiguration { return vespaconf } +// AppMetricsStruct contains xapplication metrics definition type AppMetricsStruct struct { + MoId string + MeasType string + MeasId string + MeasInterval string ObjectName string ObjectInstance string - // xxx add labels here + CounterId string } +// AppMetrics contains metrics definitions for all Xapps type AppMetrics map[string]AppMetricsStruct // Parses the metrics data from an array of bytes, which is expected to contain a JSON @@ -78,23 +114,46 @@ type AppMetrics map[string]AppMetricsStruct // // { ... // "config" : { -// "metrics": [ -// { "name": "...", "objectName": "...", "objectInstamce": "..." }, +// "measurements": [ +// { +// "metrics": [ +// { "name": "...", "objectName": "...", "objectInstamce": "..." }, +// ... +// ] +// } // ... // ] -// } +// } // } func parseMetricsFromXAppDescriptor(descriptor []byte, appMetrics AppMetrics) AppMetrics { var desc []map[string]interface{} json.Unmarshal(descriptor, &desc) for _, app := range desc { - config, config_ok := app["config"] - if config_ok { - metrics, metrics_ok := config.(map[string]interface{})["metrics"] - if metrics_ok { - parseMetricsRules(metrics.([]interface{}), appMetrics) + config, configOk := app["config"] + if !configOk { + logger.Info("No xApp config found!") + continue + } + measurements, measurementsOk := config.(map[string]interface{})["measurements"] + if !measurementsOk { + logger.Info("No xApp metrics found!") + continue + } + + for _, m := range measurements.([]interface{}) { + moId, moIdOk := m.(map[string]interface{})["moId"].(string) + measType, measTypeOk := m.(map[string]interface{})["measType"].(string) + measId, measIdOk := m.(map[string]interface{})["measId"].(string) + measInterval, measIntervalOk := m.(map[string]interface{})["measInterval"].(string) + metrics, metricsOk := m.(map[string]interface{})["metrics"] + if !metricsOk || !measTypeOk || !measIdOk || !moIdOk || !measIntervalOk { + logger.Info("No metrics found for moId=%s measType=%s measId=%s measInterval=%s", moId, measId, measType, measInterval) + continue } + logger.Info("Parsed measurement: moId=%s type=%s id=%s interval=%s", moId, measType, measId, measInterval) + + parseMetricsRules(metrics.([]interface{}), appMetrics, moId, measType, measId, measInterval) } } return appMetrics @@ -104,18 +163,19 @@ func parseMetricsFromXAppDescriptor(descriptor []byte, appMetrics AppMetrics) Ap // of the following format: // { "name": xxx, "objectName": yyy, "objectInstance": zzz } // Entries, which do not have all the necessary fields, are ignored. -func parseMetricsRules(metricsMap []interface{}, appMetrics AppMetrics) AppMetrics { +func parseMetricsRules(metricsMap []interface{}, appMetrics AppMetrics, moId, measType, measId, measInterval string) AppMetrics { for _, element := range metricsMap { - name, name_ok := element.(map[string]interface{})["name"].(string) - if name_ok { - _, already_found := appMetrics[name] - objectName, objectName_ok := element.(map[string]interface{})["objectName"].(string) - objectInstance, objectInstance_ok := element.(map[string]interface{})["objectInstance"].(string) - if !already_found && objectName_ok && objectInstance_ok { - appMetrics[name] = AppMetricsStruct{objectName, objectInstance} - logger.Info("parsed counter %s %s %s", name, objectName, objectInstance) + name, nameOk := element.(map[string]interface{})["name"].(string) + if nameOk { + _, alreadyFound := appMetrics[name] + objectName, objectNameOk := element.(map[string]interface{})["objectName"].(string) + objectInstance, objectInstanceOk := element.(map[string]interface{})["objectInstance"].(string) + counterId, counterIdOk := element.(map[string]interface{})["counterId"].(string) + if !alreadyFound && objectNameOk && objectInstanceOk && counterIdOk { + appMetrics[name] = AppMetricsStruct{moId, measType, measId, measInterval, objectName, objectInstance, counterId} + logger.Info("Parsed counter name=%s %s/%s M%sC%s", name, objectName, objectInstance, measId, counterId) } - if already_found { + if alreadyFound { logger.Info("skipped duplicate counter %s", name) } } @@ -123,35 +183,34 @@ func parseMetricsRules(metricsMap []interface{}, appMetrics AppMetrics) AppMetri return appMetrics } -func getRules(vespaconf *VESAgentConfiguration, xAppConfig []byte) { - appMetrics := make(AppMetrics) - parseMetricsFromXAppDescriptor(xAppConfig, appMetrics) - - makeRule := func(expr string, obj_name string, obj_instance string) MetricRule { +func getRules(vespaconf *VESAgentConfiguration, xAppConfig []byte) bool { + makeRule := func(expr string, value AppMetricsStruct) MetricRule { return MetricRule{ Target: "AdditionalObjects", Expr: expr, - ObjectInstance: obj_instance, - ObjectName: obj_name, + ObjectInstance: fmt.Sprintf("%s:%s", value.ObjectInstance, value.CounterId), + ObjectName: value.ObjectName, ObjectKeys: []Label{ - Label{ - Name: "ricComponentName", - Expr: "'{{.labels.kubernetes_name}}'", - }, + {Name: "ricComponentName", Expr: "'{{.labels.kubernetes_name}}'"}, + {Name: "moId", Expr: value.MoId}, + {Name: "measType", Expr: value.MeasType}, + {Name: "measId", Expr: value.MeasId}, + {Name: "measInterval", Expr: value.MeasInterval}, }, } } - var metricsMap map[string][]interface{} - json.Unmarshal(xAppConfig, &metricsMap) - metrics := parseMetricsRules(metricsMap["metrics"], appMetrics) + appMetrics := make(AppMetrics) + metrics := parseMetricsFromXAppDescriptor(xAppConfig, appMetrics) vespaconf.Measurement.Prometheus.Rules.Metrics = make([]MetricRule, 0, len(metrics)) for key, value := range metrics { - vespaconf.Measurement.Prometheus.Rules.Metrics = append(vespaconf.Measurement.Prometheus.Rules.Metrics, makeRule(key, value.ObjectName, value.ObjectInstance)) + vespaconf.Measurement.Prometheus.Rules.Metrics = append(vespaconf.Measurement.Prometheus.Rules.Metrics, makeRule(key, value)) } if len(vespaconf.Measurement.Prometheus.Rules.Metrics) == 0 { logger.Info("vespa config with empty metrics") } + + return len(vespaconf.Measurement.Prometheus.Rules.Metrics) > 0 } func getCollectorConfiguration(vespaconf *VESAgentConfiguration) { @@ -161,15 +220,17 @@ func getCollectorConfiguration(vespaconf *VESAgentConfiguration) { vespaconf.PrimaryCollector.FQDN = os.Getenv("VESMGR_PRICOLLECTOR_ADDR") vespaconf.PrimaryCollector.ServerRoot = os.Getenv("VESMGR_PRICOLLECTOR_SERVERROOT") vespaconf.PrimaryCollector.Topic = os.Getenv("VESMGR_PRICOLLECTOR_TOPIC") - port_str := os.Getenv("VESMGR_PRICOLLECTOR_PORT") - if port_str == "" { + portStr := os.Getenv("VESMGR_PRICOLLECTOR_PORT") + + if portStr == "" { vespaconf.PrimaryCollector.Port = 8443 } else { - port, _ := strconv.Atoi(port_str) + port, _ := strconv.Atoi(portStr) vespaconf.PrimaryCollector.Port = port } - secure_str := os.Getenv("VESMGR_PRICOLLECTOR_SECURE") - if secure_str == "true" { + + secureStr := os.Getenv("VESMGR_PRICOLLECTOR_SECURE") + if secureStr == "true" { vespaconf.PrimaryCollector.Secure = true } else { vespaconf.PrimaryCollector.Secure = false @@ -178,8 +239,11 @@ func getCollectorConfiguration(vespaconf *VESAgentConfiguration) { func createVespaConfig(writer io.Writer, xAppStatus []byte) { vespaconf := basicVespaConf() + getRules(&vespaconf, xAppStatus) + getCollectorConfiguration(&vespaconf) + err := yaml.NewEncoder(writer).Encode(vespaconf) if err != nil { logger.Error("Cannot write vespa conf file: %s", err.Error())