[ARVADOS] created: 8690785168e12635ce35614c02d557fe77a3fe25

Git user git at public.curoverse.com
Fri May 12 17:22:08 EDT 2017


        at  8690785168e12635ce35614c02d557fe77a3fe25 (commit)


commit 8690785168e12635ce35614c02d557fe77a3fe25
Author: Tom Clegg <tom at curoverse.com>
Date:   Fri May 12 17:21:00 2017 -0400

    11644: Add /mounts endpoint using random mount UUIDs assigned at runtime.

diff --git a/services/keepstore/handlers.go b/services/keepstore/handlers.go
index adaaa36..789d97b 100644
--- a/services/keepstore/handlers.go
+++ b/services/keepstore/handlers.go
@@ -13,7 +13,6 @@ import (
 	"crypto/md5"
 	"encoding/json"
 	"fmt"
-	"github.com/gorilla/mux"
 	"io"
 	"net/http"
 	"os"
@@ -24,6 +23,8 @@ import (
 	"sync"
 	"time"
 
+	"github.com/gorilla/mux"
+
 	"git.curoverse.com/arvados.git/sdk/go/httpserver"
 	log "github.com/Sirupsen/logrus"
 )
@@ -59,6 +60,9 @@ func MakeRESTRouter() *router {
 	// List volumes: path, device number, bytes used/avail.
 	rest.HandleFunc(`/status.json`, rtr.StatusHandler).Methods("GET", "HEAD")
 
+	// List mounts: UUID, readonly, tier, device ID, ...
+	rest.HandleFunc(`/mounts`, rtr.Mounts).Methods("GET")
+
 	// Replace the current pull queue.
 	rest.HandleFunc(`/pull`, PullHandler).Methods("PUT")
 
@@ -249,6 +253,14 @@ func IndexHandler(resp http.ResponseWriter, req *http.Request) {
 	resp.Write([]byte{'\n'})
 }
 
+// Mounts responds to "GET /mounts" requests.
+func (rtr *router) Mounts(resp http.ResponseWriter, req *http.Request) {
+	err := json.NewEncoder(resp).Encode(KeepVM.Mounts())
+	if err != nil {
+		http.Error(resp, err.Error(), http.StatusInternalServerError)
+	}
+}
+
 // PoolStatus struct
 type PoolStatus struct {
 	Alloc uint64 `json:"BytesAllocated"`
diff --git a/services/keepstore/volume.go b/services/keepstore/volume.go
index 778f27f..7e001a2 100644
--- a/services/keepstore/volume.go
+++ b/services/keepstore/volume.go
@@ -2,7 +2,9 @@ package main
 
 import (
 	"context"
+	"crypto/rand"
 	"io"
+	"math/big"
 	"sync/atomic"
 	"time"
 )
@@ -241,6 +243,9 @@ type VolumeWithExamples interface {
 // A VolumeManager tells callers which volumes can read, which volumes
 // can write, and on which volume the next write should be attempted.
 type VolumeManager interface {
+	// Mounts returns all mounts (volume attachments).
+	Mounts() []*VolumeMount
+
 	// AllReadable returns all volumes.
 	AllReadable() []Volume
 
@@ -263,10 +268,35 @@ type VolumeManager interface {
 	Close()
 }
 
+// A VolumeMount is an attachment of a Volume to a VolumeManager.
+type VolumeMount struct {
+	UUID     string
+	DeviceID string
+	ReadOnly bool
+	Tier     int
+	volume   Volume
+}
+
+// Generate a UUID the way API server would for a "KeepVolumeMount"
+// object.
+func (*VolumeMount) generateUUID() string {
+	var max big.Int
+	_, ok := max.SetString("zzzzzzzzzzzzzzz", 36)
+	if !ok {
+		panic("big.Int parse failed")
+	}
+	r, err := rand.Int(rand.Reader, &max)
+	if err != nil {
+		panic(err)
+	}
+	return "zzzzz-ivpuk-" + r.Text(36)
+}
+
 // RRVolumeManager is a round-robin VolumeManager: the Nth call to
 // NextWritable returns the (N % len(writables))th writable Volume
 // (where writables are all Volumes v where v.Writable()==true).
 type RRVolumeManager struct {
+	mounts    []*VolumeMount
 	readables []Volume
 	writables []Volume
 	counter   uint32
@@ -279,7 +309,20 @@ func MakeRRVolumeManager(volumes []Volume) *RRVolumeManager {
 		iostats: make(map[Volume]*ioStats),
 	}
 	for _, v := range volumes {
+		mnt := &VolumeMount{
+			UUID:     (*VolumeMount)(nil).generateUUID(),
+			DeviceID: "",
+			ReadOnly: !v.Writable(),
+			Tier:     1,
+			volume:   v,
+		}
+		if v, ok := v.(interface {
+			DeviceID() string
+		}); ok {
+			mnt.DeviceID = v.DeviceID()
+		}
 		vm.iostats[v] = &ioStats{}
+		vm.mounts = append(vm.mounts, mnt)
 		vm.readables = append(vm.readables, v)
 		if v.Writable() {
 			vm.writables = append(vm.writables, v)
@@ -288,6 +331,10 @@ func MakeRRVolumeManager(volumes []Volume) *RRVolumeManager {
 	return vm
 }
 
+func (vm *RRVolumeManager) Mounts() []*VolumeMount {
+	return vm.mounts
+}
+
 // AllReadable returns an array of all readable volumes
 func (vm *RRVolumeManager) AllReadable() []Volume {
 	return vm.readables

-----------------------------------------------------------------------


hooks/post-receive
-- 




More information about the arvados-commits mailing list