From 24f140f9ed1a2180541c0c7cebf7572c5155fe27 Mon Sep 17 00:00:00 2001 From: Tom Clegg Date: Mon, 6 Dec 2021 19:32:34 -0500 Subject: [PATCH] 18547: Error out if two volumes return the same non-empty DeviceID. Arvados-DCO-1.1-Signed-off-by: Tom Clegg --- services/keep-balance/balance.go | 24 +++++++++++++++++++++ services/keep-balance/balance_run_test.go | 26 +++++++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/services/keep-balance/balance.go b/services/keep-balance/balance.go index fa01d512bc..eb6f580f43 100644 --- a/services/keep-balance/balance.go +++ b/services/keep-balance/balance.go @@ -8,6 +8,7 @@ import ( "bytes" "context" "crypto/md5" + "errors" "fmt" "io" "io/ioutil" @@ -266,6 +267,29 @@ func (bal *Balancer) CheckSanityEarly(c *arvados.Client) error { } } + mountProblem := false + type deviceMount struct { + srv *KeepService + mnt *KeepMount + } + deviceMounted := map[string]deviceMount{} // DeviceID -> mount + for _, srv := range bal.KeepServices { + for _, mnt := range srv.mounts { + if first, dup := deviceMounted[mnt.DeviceID]; dup && first.mnt.UUID != mnt.UUID && mnt.DeviceID != "" { + bal.logf("config error: device %s is mounted with multiple volume UUIDs: %s on %s, and %s on %s", + mnt.DeviceID, + first.mnt.UUID, first.srv, + mnt.UUID, srv) + mountProblem = true + continue + } + deviceMounted[mnt.DeviceID] = deviceMount{srv, mnt} + } + } + if mountProblem { + return errors.New("cannot continue with config errors (see above)") + } + var checkPage arvados.CollectionList if err = c.RequestAndDecode(&checkPage, "GET", "arvados/v1/collections", nil, arvados.ResourceListParams{ Limit: new(int), diff --git a/services/keep-balance/balance_run_test.go b/services/keep-balance/balance_run_test.go index 4e2c6803ca..0d1b6b5912 100644 --- a/services/keep-balance/balance_run_test.go +++ b/services/keep-balance/balance_run_test.go @@ -397,6 +397,32 @@ func (s *runSuite) TestRefuseNonAdmin(c *check.C) { c.Check(pullReqs.Count(), check.Equals, 0) } +func (s *runSuite) TestRefuseSameDeviceDifferentVolumes(c *check.C) { + opts := RunOptions{ + CommitPulls: true, + CommitTrash: true, + Logger: ctxlog.TestLogger(c), + } + s.stub.serveCurrentUserAdmin() + s.stub.serveZeroCollections() + s.stub.serveKeepServices(stubServices) + s.stub.mux.HandleFunc("/mounts", func(w http.ResponseWriter, r *http.Request) { + hostid := r.Host[:5] // "keep0.zzzzz.arvadosapi.com:25107" => "keep0" + json.NewEncoder(w).Encode([]arvados.KeepMount{{ + UUID: "zzzzz-ivpuk-0000000000" + hostid, + DeviceID: "keep0-vol0", + StorageClasses: map[string]bool{"default": true}, + }}) + }) + trashReqs := s.stub.serveKeepstoreTrash() + pullReqs := s.stub.serveKeepstorePull() + srv := s.newServer(&opts) + _, err := srv.runOnce() + c.Check(err, check.ErrorMatches, "cannot continue with config errors.*") + c.Check(trashReqs.Count(), check.Equals, 0) + c.Check(pullReqs.Count(), check.Equals, 0) +} + func (s *runSuite) TestWriteLostBlocks(c *check.C) { lostf, err := ioutil.TempFile("", "keep-balance-lost-blocks-test-") c.Assert(err, check.IsNil) -- 2.30.2