blob: ef8e02b559f0f5366755d86d41f7c63eea326a04 [file] [log] [blame]
// Copyright 2018-present Open Networking Foundation
// Copyright 2018-present Edgecore Networks Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// 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.
package main
import (
"encoding/json"
logrus "github.com/sirupsen/logrus"
"io/ioutil"
"net/http"
)
/* parse_map() parses the json structure, amap, and returns all sub-folder paths found at the 2nd level of the multiplayer structure
*/
func parse_map(amap map[string]interface{}, level uint, archive map[string]bool) (paths []string) {
level = level + 1
for key, val := range amap {
switch val.(type) {
case map[string]interface{}:
p := parse_map(val.(map[string]interface{}), level, archive)
paths = append(paths, p...)
case []interface{}:
p := parse_array(val.([]interface{}), level, archive)
paths = append(paths, p...)
default:
if level == 2 && key == "@odata.id" {
/* sub-folder path of a resource can be found as the value of the key '@odata.id' showing up at the 2nd level of the data read from a resource. When a path is found, it's checked against the array 'archive' to avoid duplicates. */
if _, ok := archive[val.(string)]; !ok {
archive[val.(string)] = true
paths = append(paths, val.(string))
}
}
}
}
return paths
}
/* parse_array() parses any vlaue, if in the form of an array, of a key-value pair found in the json structure, and returns any paths found.
*/
func parse_array(anarray []interface{}, level uint, archive map[string]bool) (paths []string) {
for _, val := range anarray {
switch val.(type) {
case map[string]interface{}:
p := parse_map(val.(map[string]interface{}), level, archive)
paths = append(paths, p...)
}
}
return paths
}
/* read_resource() reads data from the specified Redfish resource, including its sub-folders, of the specified device ip and rerutnrs the data read.
Based on careful examination of the data returned from several resources sampled, it was determined that sub-folder paths can be found as the value to the key '@odata.id' showing up at the 2nd level of the data read from a resource.
*/
func read_resource(ip string, resource string, archive map[string]bool) (data []string) {
resp, err := http.Get(ip + resource)
if resp != nil {
defer resp.Body.Close()
}
if err != nil {
logrus.Errorf("Error http get %s", err)
return
}
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
logrus.Errorf("Error Read %s", err)
return
}
data = append(data, string(body))
m := map[string]interface{}{}
err = json.Unmarshal([]byte(body), &m)
if err != nil {
logrus.Errorf("Error Unmarshal %s", err)
return
}
resources := parse_map(m, 0, archive)
for _, resource := range resources {
d := read_resource(ip, resource, archive)
data = append(data, d...)
}
return data
}
/* sample JSON files can be found in the samples folder */
func (s *Server) get_status(ip string, resource string) (data []string) {
archive := make(map[string]bool)
base_ip := RF_DEFAULT_PROTOCOL + ip
/* 'archive' maintains a list of all resources that will be/have been visited to avoid duplicates */
archive[resource] = true
data = read_resource(base_ip, resource, archive)
return data
}