16 // DiscoverKeepServers gets list of available keep services from the
19 // If a list of services is provided in the arvadosclient (e.g., from
20 // an environment variable or local config), that list is used
22 func (this *KeepClient) DiscoverKeepServers() error {
23 if this.Arvados.KeepServiceURIs != nil {
24 this.foundNonDiskSvc = true
25 this.replicasPerService = 0
26 if c, ok := this.Client.(*http.Client); ok {
27 this.setClientSettingsNonDisk(c)
29 roots := make(map[string]string)
30 for i, uri := range this.Arvados.KeepServiceURIs {
31 roots[fmt.Sprintf("00000-bi6l4-%015d", i)] = uri
33 this.SetServiceRoots(roots, roots, roots)
37 // ArvadosClient did not provide a services list. Ask API
38 // server for a list of accessible services.
40 err := this.Arvados.Call("GET", "keep_services", "", "accessible", nil, &list)
44 return this.loadKeepServers(list)
47 // LoadKeepServicesFromJSON gets list of available keep services from given JSON
48 func (this *KeepClient) LoadKeepServicesFromJSON(services string) error {
51 // Load keep services from given json
52 dec := json.NewDecoder(strings.NewReader(services))
53 if err := dec.Decode(&list); err != nil {
57 return this.loadKeepServers(list)
60 // RefreshServices calls DiscoverKeepServers to refresh the keep
61 // service list on SIGHUP; when the given interval has elapsed since
62 // the last refresh; and (if the last refresh failed) the given
63 // errInterval has elapsed.
64 func (kc *KeepClient) RefreshServices(interval, errInterval time.Duration) {
65 var previousRoots = []map[string]string{}
67 timer := time.NewTimer(interval)
68 gotHUP := make(chan os.Signal, 1)
69 signal.Notify(gotHUP, syscall.SIGHUP)
78 if err := kc.DiscoverKeepServers(); err != nil {
79 log.Printf("WARNING: Error retrieving services list: %v (retrying in %v)", err, errInterval)
80 timer.Reset(errInterval)
83 newRoots := []map[string]string{kc.LocalRoots(), kc.GatewayRoots()}
85 if !reflect.DeepEqual(previousRoots, newRoots) {
86 DebugPrintf("DEBUG: Updated services list: locals %v gateways %v", newRoots[0], newRoots[1])
87 previousRoots = newRoots
90 if len(newRoots[0]) == 0 {
91 log.Printf("WARNING: No local services (retrying in %v)", errInterval)
92 timer.Reset(errInterval)
98 func (this *KeepClient) loadKeepServers(list svcList) error {
99 listed := make(map[string]bool)
100 localRoots := make(map[string]string)
101 gatewayRoots := make(map[string]string)
102 writableLocalRoots := make(map[string]string)
104 // replicasPerService is 1 for disks; unknown or unlimited otherwise
105 this.replicasPerService = 1
107 for _, service := range list.Items {
112 url := fmt.Sprintf("%s://%s:%d", scheme, service.Hostname, service.Port)
120 localRoots[service.Uuid] = url
121 if service.ReadOnly == false {
122 writableLocalRoots[service.Uuid] = url
123 if service.SvcType != "disk" {
124 this.replicasPerService = 0
128 if service.SvcType != "disk" {
129 this.foundNonDiskSvc = true
132 // Gateway services are only used when specified by
133 // UUID, so there's nothing to gain by filtering them
134 // by service type. Including all accessible services
135 // (gateway and otherwise) merely accommodates more
136 // service configurations.
137 gatewayRoots[service.Uuid] = url
140 if client, ok := this.Client.(*http.Client); ok {
141 if this.foundNonDiskSvc {
142 this.setClientSettingsNonDisk(client)
144 this.setClientSettingsDisk(client)
148 this.SetServiceRoots(localRoots, writableLocalRoots, gatewayRoots)