github.com/NVIDIA/aistore@v1.3.23-0.20240517131212-7df6609be51d/api/daemon.go (about) 1 // Package api provides native Go-based API/SDK over HTTP(S). 2 /* 3 * Copyright (c) 2018-2024, NVIDIA CORPORATION. All rights reserved. 4 */ 5 package api 6 7 import ( 8 "io" 9 "net/http" 10 "net/url" 11 "strconv" 12 13 "github.com/NVIDIA/aistore/api/apc" 14 "github.com/NVIDIA/aistore/cmn" 15 "github.com/NVIDIA/aistore/cmn/cos" 16 "github.com/NVIDIA/aistore/core/meta" 17 "github.com/NVIDIA/aistore/ios" 18 ) 19 20 type GetLogInput struct { 21 Writer io.Writer 22 Severity string // one of: {cmn.LogInfo, ...} 23 Offset int64 24 All bool 25 } 26 27 // GetMountpaths given the direct public URL of the target, returns the target's mountpaths or error. 28 func GetMountpaths(bp BaseParams, node *meta.Snode) (mpl *apc.MountpathList, err error) { 29 bp.Method = http.MethodGet 30 reqParams := AllocRp() 31 { 32 reqParams.BaseParams = bp 33 reqParams.Path = apc.URLPathReverseDae.S 34 reqParams.Query = url.Values{apc.QparamWhat: []string{apc.WhatMountpaths}} 35 reqParams.Header = http.Header{ 36 apc.HdrNodeID: []string{node.ID()}, 37 apc.HdrNodeURL: []string{node.URL(cmn.NetPublic)}, 38 } 39 } 40 _, err = reqParams.DoReqAny(&mpl) 41 FreeRp(reqParams) 42 return mpl, err 43 } 44 45 func AttachMountpath(bp BaseParams, node *meta.Snode, mountpath string, label ...ios.Label) error { 46 bp.Method = http.MethodPut 47 reqParams := AllocRp() 48 { 49 reqParams.BaseParams = bp 50 reqParams.Path = apc.URLPathReverseDae.Join(apc.Mountpaths) 51 reqParams.Body = cos.MustMarshal(apc.ActMsg{Action: apc.ActMountpathAttach, Value: mountpath}) 52 reqParams.Header = http.Header{ 53 apc.HdrNodeID: []string{node.ID()}, 54 apc.HdrNodeURL: []string{node.URL(cmn.NetPublic)}, 55 cos.HdrContentType: []string{cos.ContentJSON}, 56 } 57 if len(label) > 0 { 58 if lb := string(label[0]); lb != "" { 59 reqParams.Query = url.Values{apc.QparamMpathLabel: []string{lb}} 60 } 61 } 62 } 63 err := reqParams.DoRequest() 64 FreeRp(reqParams) 65 return err 66 } 67 68 func EnableMountpath(bp BaseParams, node *meta.Snode, mountpath string) error { 69 bp.Method = http.MethodPost 70 reqParams := AllocRp() 71 { 72 reqParams.BaseParams = bp 73 reqParams.Path = apc.URLPathReverseDae.Join(apc.Mountpaths) 74 reqParams.Body = cos.MustMarshal(apc.ActMsg{Action: apc.ActMountpathEnable, Value: mountpath}) 75 reqParams.Header = http.Header{ 76 apc.HdrNodeID: []string{node.ID()}, 77 apc.HdrNodeURL: []string{node.URL(cmn.NetPublic)}, 78 cos.HdrContentType: []string{cos.ContentJSON}, 79 } 80 } 81 err := reqParams.DoRequest() 82 FreeRp(reqParams) 83 return err 84 } 85 86 func DetachMountpath(bp BaseParams, node *meta.Snode, mountpath string, dontResilver bool) error { 87 var q url.Values 88 if dontResilver { 89 q = url.Values{apc.QparamDontResilver: []string{"true"}} 90 } 91 bp.Method = http.MethodDelete 92 reqParams := AllocRp() 93 { 94 reqParams.BaseParams = bp 95 reqParams.Path = apc.URLPathReverseDae.Join(apc.Mountpaths) 96 reqParams.Body = cos.MustMarshal(apc.ActMsg{Action: apc.ActMountpathDetach, Value: mountpath}) 97 reqParams.Header = http.Header{ 98 apc.HdrNodeID: []string{node.ID()}, 99 cos.HdrContentType: []string{cos.ContentJSON}, 100 } 101 reqParams.Query = q 102 } 103 err := reqParams.DoRequest() 104 FreeRp(reqParams) 105 return err 106 } 107 108 func DisableMountpath(bp BaseParams, node *meta.Snode, mountpath string, dontResilver bool) error { 109 var q url.Values 110 if dontResilver { 111 q = url.Values{apc.QparamDontResilver: []string{"true"}} 112 } 113 bp.Method = http.MethodPost 114 reqParams := AllocRp() 115 { 116 reqParams.BaseParams = bp 117 reqParams.Path = apc.URLPathReverseDae.Join(apc.Mountpaths) 118 reqParams.Body = cos.MustMarshal(apc.ActMsg{Action: apc.ActMountpathDisable, Value: mountpath}) 119 reqParams.Header = http.Header{ 120 apc.HdrNodeID: []string{node.ID()}, 121 cos.HdrContentType: []string{cos.ContentJSON}, 122 } 123 reqParams.Query = q 124 } 125 err := reqParams.DoRequest() 126 FreeRp(reqParams) 127 return err 128 } 129 130 // GetDaemonConfig returns the configuration of a specific daemon in a cluster. 131 // (compare with `api.GetClusterConfig`) 132 func GetDaemonConfig(bp BaseParams, node *meta.Snode) (config *cmn.Config, err error) { 133 bp.Method = http.MethodGet 134 reqParams := AllocRp() 135 { 136 reqParams.BaseParams = bp 137 reqParams.Path = apc.URLPathReverseDae.S 138 reqParams.Query = url.Values{apc.QparamWhat: []string{apc.WhatNodeConfig}} 139 reqParams.Header = http.Header{apc.HdrNodeID: []string{node.ID()}} 140 } 141 _, err = reqParams.DoReqAny(&config) 142 FreeRp(reqParams) 143 if err != nil { 144 return nil, err 145 } 146 // FIXME: transform backend structures on the client side 147 // as a side effect, config.Backend validation populates non-JSON structs that client can utilize; 148 _ = config.Backend.Validate() 149 return config, nil 150 } 151 152 // names _and_ kinds, i.e. (name, kind) pairs 153 func GetMetricNames(bp BaseParams, node *meta.Snode) (kvs cos.StrKVs, err error) { 154 bp.Method = http.MethodGet 155 reqParams := AllocRp() 156 { 157 reqParams.BaseParams = bp 158 reqParams.Path = apc.URLPathReverseDae.S 159 reqParams.Query = url.Values{apc.QparamWhat: []string{apc.WhatMetricNames}} 160 reqParams.Header = http.Header{apc.HdrNodeID: []string{node.ID()}} 161 } 162 _, err = reqParams.DoReqAny(&kvs) 163 FreeRp(reqParams) 164 return 165 } 166 167 // Returns log of a specific node in a cluster. 168 func GetDaemonLog(bp BaseParams, node *meta.Snode, args GetLogInput) (int64, error) { 169 w := args.Writer 170 q := make(url.Values, 3) 171 q.Set(apc.QparamWhat, apc.WhatLog) 172 if args.Severity != "" { 173 q.Set(apc.QparamLogSev, args.Severity) 174 } 175 if args.Offset != 0 { 176 q.Set(apc.QparamLogOff, strconv.FormatInt(args.Offset, 10)) 177 } 178 if args.All { 179 q.Set(apc.QparamAllLogs, "true") 180 } 181 bp.Method = http.MethodGet 182 reqParams := AllocRp() 183 { 184 reqParams.BaseParams = bp 185 reqParams.Path = apc.URLPathReverseDae.S 186 reqParams.Query = q 187 reqParams.Header = http.Header{apc.HdrNodeID: []string{node.ID()}} 188 } 189 wrap, err := reqParams.doWriter(w) 190 FreeRp(reqParams) 191 if err == nil { 192 return wrap.n, nil 193 } 194 return 0, err 195 } 196 197 // SetDaemonConfig, given key value pairs, sets the configuration accordingly for a specific node. 198 func SetDaemonConfig(bp BaseParams, nodeID string, nvs cos.StrKVs, transient ...bool) error { 199 bp.Method = http.MethodPut 200 query := url.Values{} 201 for key, val := range nvs { 202 query.Add(key, val) 203 } 204 if len(transient) > 0 { 205 query.Add(apc.ActTransient, strconv.FormatBool(transient[0])) 206 } 207 reqParams := AllocRp() 208 { 209 reqParams.BaseParams = bp 210 reqParams.Path = apc.URLPathReverseDae.Join(apc.ActSetConfig) 211 reqParams.Query = query 212 reqParams.Header = http.Header{apc.HdrNodeID: []string{nodeID}} 213 } 214 err := reqParams.DoRequest() 215 FreeRp(reqParams) 216 return err 217 } 218 219 // reset node's configuration to cluster defaults 220 func ResetDaemonConfig(bp BaseParams, nodeID string) error { 221 return _putDaemon(bp, nodeID, apc.ActMsg{Action: apc.ActResetConfig}) 222 } 223 224 func RotateLogs(bp BaseParams, nodeID string) error { 225 return _putDaemon(bp, nodeID, apc.ActMsg{Action: apc.ActRotateLogs}) 226 } 227 228 func _putDaemon(bp BaseParams, nodeID string, msg apc.ActMsg) error { 229 bp.Method = http.MethodPut 230 reqParams := AllocRp() 231 { 232 reqParams.BaseParams = bp 233 reqParams.Path = apc.URLPathReverseDae.S 234 reqParams.Body = cos.MustMarshal(msg) 235 reqParams.Header = http.Header{ 236 apc.HdrNodeID: []string{nodeID}, 237 cos.HdrContentType: []string{cos.ContentJSON}, 238 } 239 } 240 err := reqParams.DoRequest() 241 FreeRp(reqParams) 242 return err 243 }