mc | e702840 | 2019-07-18 04:10:01 +0000 | [diff] [blame] | 1 | // Copyright 2018 Open Networking Foundation |
| 2 | // |
| 3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | // you may not use this file except in compliance with the License. |
| 5 | // You may obtain a copy of the License at |
| 6 | // |
| 7 | // http://www.apache.org/licenses/LICENSE-2.0 |
| 8 | // |
| 9 | // Unless required by applicable law or agreed to in writing, software |
| 10 | // distributed under the License is distributed on an "AS IS" BASIS, |
| 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 | // See the License for the specific language governing permissions and |
| 13 | // limitations under the License. |
| 14 | |
| 15 | package main |
| 16 | |
| 17 | import ( |
mc | e702840 | 2019-07-18 04:10:01 +0000 | [diff] [blame] | 18 | "encoding/json" |
Dinesh Belwalkar | 72ecafb | 2019-12-12 00:08:56 +0000 | [diff] [blame] | 19 | "fmt" |
mc | e702840 | 2019-07-18 04:10:01 +0000 | [diff] [blame] | 20 | "io/ioutil" |
Dinesh Belwalkar | 72ecafb | 2019-12-12 00:08:56 +0000 | [diff] [blame] | 21 | "net/http" |
mc | e702840 | 2019-07-18 04:10:01 +0000 | [diff] [blame] | 22 | ) |
| 23 | |
mc | 20a4b5f | 2019-10-16 20:28:24 +0000 | [diff] [blame] | 24 | /* parse_map() parses the json structure, amap, and returns all sub-folder paths found at the 2nd level of the multiplayer structure |
Dinesh Belwalkar | 72ecafb | 2019-12-12 00:08:56 +0000 | [diff] [blame] | 25 | */ |
mc | 20a4b5f | 2019-10-16 20:28:24 +0000 | [diff] [blame] | 26 | func parse_map(amap map[string]interface{}, level uint, archive map[string]bool) (paths []string) { |
| 27 | level = level + 1 |
| 28 | for key, val := range amap { |
| 29 | switch val.(type) { |
| 30 | case map[string]interface{}: |
| 31 | p := parse_map(val.(map[string]interface{}), level, archive) |
| 32 | paths = append(paths, p...) |
| 33 | case []interface{}: |
| 34 | p := parse_array(val.([]interface{}), level, archive) |
| 35 | paths = append(paths, p...) |
| 36 | default: |
| 37 | if level == 2 && key == "@odata.id" { |
Dinesh Belwalkar | 72ecafb | 2019-12-12 00:08:56 +0000 | [diff] [blame] | 38 | /* 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. */ |
mc | 20a4b5f | 2019-10-16 20:28:24 +0000 | [diff] [blame] | 39 | if _, ok := archive[val.(string)]; !ok { |
| 40 | archive[val.(string)] = true |
| 41 | paths = append(paths, val.(string)) |
| 42 | } |
| 43 | } |
| 44 | } |
| 45 | } |
| 46 | return paths |
| 47 | } |
mc | e702840 | 2019-07-18 04:10:01 +0000 | [diff] [blame] | 48 | |
mc | 20a4b5f | 2019-10-16 20:28:24 +0000 | [diff] [blame] | 49 | /* 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. |
Dinesh Belwalkar | 72ecafb | 2019-12-12 00:08:56 +0000 | [diff] [blame] | 50 | */ |
mc | 20a4b5f | 2019-10-16 20:28:24 +0000 | [diff] [blame] | 51 | func parse_array(anarray []interface{}, level uint, archive map[string]bool) (paths []string) { |
| 52 | for _, val := range anarray { |
| 53 | switch val.(type) { |
| 54 | case map[string]interface{}: |
| 55 | p := parse_map(val.(map[string]interface{}), level, archive) |
| 56 | paths = append(paths, p...) |
| 57 | } |
| 58 | } |
| 59 | return paths |
| 60 | } |
| 61 | |
| 62 | /* read_resource() reads data from the specified Redfish resource, including its sub-folders, of the specified device ip and rerutnrs the data read. |
| 63 | |
| 64 | 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. |
| 65 | */ |
| 66 | func read_resource(ip string, resource string, archive map[string]bool) (data []string) { |
| 67 | resp, err := http.Get(ip + resource) |
| 68 | if resp != nil { |
| 69 | defer resp.Body.Close() |
| 70 | } |
mc | e702840 | 2019-07-18 04:10:01 +0000 | [diff] [blame] | 71 | if err != nil { |
| 72 | fmt.Println(err) |
| 73 | return |
| 74 | } |
mc | 20a4b5f | 2019-10-16 20:28:24 +0000 | [diff] [blame] | 75 | body, err := ioutil.ReadAll(resp.Body) |
| 76 | if err != nil { |
| 77 | fmt.Println(err) |
| 78 | return |
mc | e702840 | 2019-07-18 04:10:01 +0000 | [diff] [blame] | 79 | } |
mc | 20a4b5f | 2019-10-16 20:28:24 +0000 | [diff] [blame] | 80 | |
| 81 | data = append(data, string(body)) |
| 82 | |
| 83 | m := map[string]interface{}{} |
| 84 | err = json.Unmarshal([]byte(body), &m) |
| 85 | if err != nil { |
| 86 | fmt.Println(err) |
| 87 | return |
| 88 | } |
| 89 | |
| 90 | resources := parse_map(m, 0, archive) |
| 91 | |
| 92 | for _, resource := range resources { |
| 93 | d := read_resource(ip, resource, archive) |
| 94 | data = append(data, d...) |
| 95 | } |
| 96 | return data |
| 97 | } |
| 98 | |
| 99 | /* sample JSON files can be found in the samples folder */ |
| 100 | func (s *Server) get_status(ip string, resource string) (data []string) { |
| 101 | archive := make(map[string]bool) |
| 102 | base_ip := RF_DEFAULT_PROTOCOL + ip |
| 103 | /* 'archive' maintains a list of all resources that will be/have been visited to avoid duplicates */ |
| 104 | archive[resource] = true |
| 105 | data = read_resource(base_ip, resource, archive) |
| 106 | return data |
mc | e702840 | 2019-07-18 04:10:01 +0000 | [diff] [blame] | 107 | } |