github.com/cs3org/reva/v2@v2.27.7/pkg/metrics/driver/xcloud/xcloud.go (about)

     1  // Copyright 2018-2020 CERN
     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  // In applying this license, CERN does not waive the privileges and immunities
    16  // granted to it by virtue of its status as an Intergovernmental Organization
    17  // or submit itself to any jurisdiction.
    18  
    19  package json
    20  
    21  import (
    22  	"crypto/tls"
    23  	"encoding/json"
    24  	"errors"
    25  	"fmt"
    26  	"io"
    27  	"net/http"
    28  	"os"
    29  	"sync"
    30  	"time"
    31  
    32  	"github.com/cs3org/reva/v2/pkg/metrics/driver/registry"
    33  
    34  	"github.com/rs/zerolog"
    35  
    36  	"github.com/cs3org/reva/v2/pkg/logger"
    37  	"github.com/cs3org/reva/v2/pkg/metrics/config"
    38  )
    39  
    40  var log zerolog.Logger
    41  
    42  func init() {
    43  	log = logger.New().With().Int("pid", os.Getpid()).Logger()
    44  	driver := &CloudDriver{CloudData: &CloudData{}}
    45  	registry.Register(driverName(), driver)
    46  }
    47  
    48  func driverName() string {
    49  	return "xcloud"
    50  }
    51  
    52  // CloudDriver is the driver to use for Sciencemesh apps
    53  type CloudDriver struct {
    54  	instance     string
    55  	pullInterval int
    56  	CloudData    *CloudData
    57  	sync.Mutex
    58  	client *http.Client
    59  }
    60  
    61  func (d *CloudDriver) refresh() error {
    62  	// endpoint example: https://mybox.com or https://mybox.com/owncloud
    63  	endpoint := fmt.Sprintf("%s/index.php/apps/sciencemesh/internal_metrics", d.instance)
    64  
    65  	req, err := http.NewRequest("GET", endpoint, nil)
    66  	if err != nil {
    67  		log.Err(err).Msgf("xcloud: error creating request to %s", d.instance)
    68  		return err
    69  	}
    70  
    71  	resp, err := d.client.Do(req)
    72  	if err != nil {
    73  		log.Err(err).Msgf("xcloud: error getting internal metrics from %s", d.instance)
    74  		return err
    75  	}
    76  
    77  	if resp.StatusCode != http.StatusOK {
    78  		err := fmt.Errorf("xcloud: error getting internal metrics from %s. http status code (%d)", d.instance, resp.StatusCode)
    79  		log.Err(err).Msgf("xcloud: error getting internal metrics from %s", d.instance)
    80  		return err
    81  	}
    82  	defer resp.Body.Close()
    83  
    84  	// read response body
    85  	data, err := io.ReadAll(resp.Body)
    86  	if err != nil {
    87  		log.Err(err).Msgf("xcloud: error reading resp body from internal metrics from %s", d.instance)
    88  		return err
    89  	}
    90  
    91  	cd := &CloudData{}
    92  	if err := json.Unmarshal(data, cd); err != nil {
    93  		log.Err(err).Msgf("xcloud: error parsing body from internal metrics: body(%s)", string(data))
    94  		return err
    95  	}
    96  
    97  	d.Lock()
    98  	defer d.Unlock()
    99  	d.CloudData = cd
   100  	log.Info().Msgf("xcloud: received internal metrics from cloud provider: %+v", cd)
   101  
   102  	return nil
   103  }
   104  
   105  // Configure configures this driver
   106  func (d *CloudDriver) Configure(c *config.Config) error {
   107  	if c.XcloudInstance == "" {
   108  		err := errors.New("xcloud: missing xcloud_instance config parameter")
   109  		return err
   110  	}
   111  
   112  	if c.XcloudPullInterval == 0 {
   113  		c.XcloudPullInterval = 5 // seconds
   114  	}
   115  
   116  	d.instance = c.XcloudInstance
   117  	d.pullInterval = c.XcloudPullInterval
   118  
   119  	tr := &http.Transport{
   120  		TLSClientConfig: &tls.Config{InsecureSkipVerify: c.InsecureSkipVerify},
   121  	}
   122  	client := &http.Client{Transport: tr}
   123  
   124  	d.client = client
   125  
   126  	ticker := time.NewTicker(time.Duration(d.pullInterval) * time.Second)
   127  	quit := make(chan struct{})
   128  	go func() {
   129  		for {
   130  			select {
   131  			case <-ticker.C:
   132  				err := d.refresh()
   133  				if err != nil {
   134  					log.Err(err).Msgf("xcloud: error from refresh goroutine")
   135  				}
   136  			case <-quit:
   137  				ticker.Stop()
   138  				return
   139  			}
   140  		}
   141  	}()
   142  
   143  	return nil
   144  }
   145  
   146  // GetNumUsers returns the number of site users
   147  func (d *CloudDriver) GetNumUsers() int64 {
   148  	return d.CloudData.Metrics.TotalUsers
   149  }
   150  
   151  // GetNumGroups returns the number of site groups
   152  func (d *CloudDriver) GetNumGroups() int64 {
   153  	return d.CloudData.Metrics.TotalGroups
   154  }
   155  
   156  // GetAmountStorage returns the amount of site storage used
   157  func (d *CloudDriver) GetAmountStorage() int64 {
   158  	return d.CloudData.Metrics.TotalStorage
   159  }
   160  
   161  // CloudData represents the information obtained from the sciencemesh app
   162  type CloudData struct {
   163  	Metrics  CloudDataMetrics  `json:"metrics"`
   164  	Settings CloudDataSettings `json:"settings"`
   165  }
   166  
   167  // CloudDataMetrics reprents the metrics gathered from the sciencemesh app
   168  type CloudDataMetrics struct {
   169  	TotalUsers   int64 `json:"numusers"`
   170  	TotalGroups  int64 `json:"numgroups"`
   171  	TotalStorage int64 `json:"numstorage"`
   172  }
   173  
   174  // CloudDataSettings represents the metrics gathered
   175  type CloudDataSettings struct {
   176  	IOPUrl   string `json:"iopurl"`
   177  	Sitename string `json:"sitename"`
   178  	Siteurl  string `json:"siteurl"`
   179  	Country  string `json:"country"`
   180  }