e3e90d3581517c0ae8831f76be2881aaa0f1a44c
[arvados.git] / services / keep-balance / main.go
1 // Copyright (C) The Arvados Authors. All rights reserved.
2 //
3 // SPDX-License-Identifier: AGPL-3.0
4
5 package main
6
7 import (
8         "encoding/json"
9         "flag"
10         "fmt"
11         "log"
12         "net/http"
13         "os"
14         "time"
15
16         "git.curoverse.com/arvados.git/sdk/go/arvados"
17         "git.curoverse.com/arvados.git/sdk/go/config"
18         "github.com/Sirupsen/logrus"
19 )
20
21 var debugf = func(string, ...interface{}) {}
22
23 func main() {
24         var cfg Config
25         var runOptions RunOptions
26
27         configPath := flag.String("config", defaultConfigPath,
28                 "`path` of JSON or YAML configuration file")
29         serviceListPath := flag.String("config.KeepServiceList", "",
30                 "`path` of JSON or YAML file with list of keep services to balance, as given by \"arv keep_service list\" "+
31                         "(default: config[\"KeepServiceList\"], or if none given, get all available services and filter by config[\"KeepServiceTypes\"])")
32         flag.BoolVar(&runOptions.Once, "once", false,
33                 "balance once and then exit")
34         flag.BoolVar(&runOptions.CommitPulls, "commit-pulls", false,
35                 "send pull requests (make more replicas of blocks that are underreplicated or are not in optimal rendezvous probe order)")
36         flag.BoolVar(&runOptions.CommitTrash, "commit-trash", false,
37                 "send trash requests (delete unreferenced old blocks, and excess replicas of overreplicated blocks)")
38         dumpConfig := flag.Bool("dump-config", false, "write current configuration to stdout and exit")
39         dumpFlag := flag.Bool("dump", false, "dump details for each block to stdout")
40         debugFlag := flag.Bool("debug", false, "enable debug messages")
41         getVersion := flag.Bool("version", false, "Print version information and exit.")
42         flag.Usage = usage
43         flag.Parse()
44
45         // Print version information if requested
46         if *getVersion {
47                 fmt.Printf("keep-balance %s\n", version)
48                 return
49         }
50
51         mustReadConfig(&cfg, *configPath)
52         if *serviceListPath != "" {
53                 mustReadConfig(&cfg.KeepServiceList, *serviceListPath)
54         }
55
56         if *dumpConfig {
57                 log.Fatal(config.DumpAndExit(cfg))
58         }
59
60         to := time.Duration(cfg.RequestTimeout)
61         if to == 0 {
62                 to = 30 * time.Minute
63         }
64         arvados.DefaultSecureClient.Timeout = to
65         arvados.InsecureHTTPClient.Timeout = to
66         http.DefaultClient.Timeout = to
67
68         log.Printf("keep-balance %s started", version)
69
70         if *debugFlag {
71                 debugf = log.Printf
72                 if j, err := json.Marshal(cfg); err != nil {
73                         log.Fatal(err)
74                 } else {
75                         log.Printf("config is %s", j)
76                 }
77         }
78         if *dumpFlag {
79                 runOptions.Dumper = logrus.New()
80                 runOptions.Dumper.Out = os.Stdout
81                 runOptions.Dumper.Formatter = &logrus.TextFormatter{}
82         }
83         srv, err := NewServer(cfg, runOptions)
84         if err != nil {
85                 // (don't run)
86         } else if runOptions.Once {
87                 _, err = srv.Run()
88         } else {
89                 err = srv.RunForever(nil)
90         }
91         if err != nil {
92                 log.Fatal(err)
93         }
94 }
95
96 func mustReadConfig(dst interface{}, path string) {
97         if err := config.LoadFile(dst, path); err != nil {
98                 log.Fatal(err)
99         }
100 }