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  }