Repository navigation
fix(store): find replicas and snapshots in any name spelling, store layer stacks in canonical case #217
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
Andrei Kvapil (kvaps)
wants to merge
51
commits into
main
Choose a base branch
from
fix/name-case-folding
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
fix(store): find replicas and snapshots in any name spelling, store layer stacks in canonical case #217
Changes from all commits
Commits
Show all changes
51 commits
Select commit
Hold shift + click to select a range
8363c28
fix(layer-stack): store definition and group stacks in canonical case
kvaps bfd7bee
fix(store): store a replica's parents under their CR names
kvaps 0d2a2d9
fix(controller,satellite): fold the names a replica may spell otherwise
kvaps afde53c
test(controller,satellite): pin a mixed-case replica through apply
kvaps 43ab333
fix(linstormigrate): adopt replicas and snapshots under CR names
kvaps 1e211bf
fix(dispatcher): find a peer's node under the CR name its replica stores
kvaps 4c7a1f6
fix(controller): see data on a replica stored in another spelling
kvaps 8bda503
test(store): pin the spelling annotations and the registered spelling
kvaps 5c80511
docs(migration): name on-disk volumes after the definition's CR name
kvaps f0959fc
fix(controller): match a replica's node in every spelling
kvaps ff2b566
fix(store): find a storage pool under another spelling of its node
kvaps 8674fdb
fix(controller): reach replicas, nodes and snapshot entries in any sp…
kvaps 88f0c94
fix(satellite): take snapshots and replicas that spell their node oth…
kvaps 676696e
fix(rest,cli,placer): read two spellings of a node as one node
kvaps a8912ce
docs(site): name the snapshot path after the definition's CR name
kvaps a9099db
fix(satellite): render the paths of a connection named in another spe…
kvaps d5bae26
fix(store): list a node's devices under its CR name
kvaps 7e13c2a
fix(store): fail a listing or write whose parent cannot be read
kvaps cc29f78
fix(store): list a definition's children under no other definition's …
kvaps d2fee3c
fix(store): derive the parent names a child shows, never take them fr…
kvaps 9771231
fix(rest): key nodes by their CR name in the snapshot and restore checks
kvaps f4fdb86
fix(controller): key node sets by CR name in the witness and auto-dis…
kvaps 4036c0f
fix(rest): skip replicas on evicted nodes in additional_place_count b…
kvaps 70e8f4e
fix(satellite): name a replica's resource by its definition's CR name
kvaps 256d5cf
fix(satellite): reach a replica's CR through the registered spellings
kvaps 84f7992
feat(naming): give LINSTOR names one key, in a package of its own
kvaps 5e12a28
refactor(naming): take object names through pkg/naming above the store
kvaps b4f1a4e
fix(naming): compare and key object names only as naming keys
kvaps 40a29a8
test(naming): fail on any name compared or keyed outside naming
kvaps 6461b36
fix(naming): address a CR built from a name through naming.Key
kvaps 0a55f4d
fix(satellite,cli): own a cold-start orphan, and filter pools, by nam…
kvaps 7410935
docs(rest): say list filters match names as the store keys them
kvaps b893b1e
fix(cli): refuse migrate-disk onto its own source in any spelling
kvaps 3c0650f
fix(rest): find a node connection in any spelling of its nodes
kvaps c4b9a55
fix(store): address in-memory objects by naming key, as the k8s store
kvaps 58c316b
fix(naming): keep Key idempotent for a name with no letter or digit
kvaps 506b979
fix(placer): find an existing replica's pool in any node spelling
kvaps 8ab8453
fix(rest): keep one resource-connection path entry per node pair
kvaps c6a95af
fix(rest): wait for the peer-forget ack under the removed node's key
kvaps ffd1802
refactor(controller): match a replica to its definition with Same
kvaps 01e647c
test(naming): follow names by provenance in the guard
kvaps 48db68b
fix(store): key in-memory replicas and snapshots by their CR names
kvaps de3bc89
test(naming): cover the shapes the name guard missed
kvaps 271cec3
fix(controller): never prune a migration's own destination
kvaps 3d5399e
fix(satellite): fold one node's snapshot status entries into one
kvaps c5ce7e1
fix(satellite): keep a peer whose spelling changed out of del-peer
kvaps e199774
fix(drbd): match a connection's paths to hosts in any spelling
kvaps b89eca0
test(naming): check the satellite and DRBD code, function by function
kvaps d4622b5
fix(placer): place one definition at a time, counting live replicas
kvaps a5a9b86
test(integration): start placing only once seeded pools have capacity
kvaps 73913f5
test(integration): pin the missing-pool test's group to the pool too
kvaps File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
| // SPDX-License-Identifier: Apache-2.0 | ||
|
|
||
| /* | ||
| Copyright 2026 Cozystack contributors. | ||
|
|
||
| Licensed under the Apache License, Version 2.0 (the "License"); | ||
| you may not use this file except in compliance with the License. | ||
| You may obtain a copy of the License at | ||
|
|
||
| http://www.apache.org/licenses/LICENSE-2.0 | ||
|
|
||
| Unless required by applicable law or agreed to in writing, software | ||
| distributed under the License is distributed on an "AS IS" BASIS, | ||
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| See the License for the specific language governing permissions and | ||
| limitations under the License. | ||
| */ | ||
|
|
||
| package cli | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This file needs |
||
|
|
||
| import ( | ||
| "slices" | ||
| "testing" | ||
| ) | ||
|
|
||
| // The CLI writes the CRDs directly, so it stores the stack in the same | ||
| // canonical case as the REST doors. | ||
| func TestParseLayerListStoresCanonicalCase(t *testing.T) { | ||
| t.Parallel() | ||
|
|
||
| got, err := parseLayerList("drbd,Luks,storage") | ||
| if err != nil { | ||
| t.Fatalf("parse: %v", err) | ||
| } | ||
|
|
||
| want := []string{"DRBD", "LUKS", "STORAGE"} | ||
| if !slices.Equal(got, want) { | ||
| t.Fatalf("got %v, want %v", got, want) | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,55 @@ | ||
| // SPDX-License-Identifier: Apache-2.0 | ||
|
|
||
| /* | ||
| Copyright 2026 Cozystack contributors. | ||
|
|
||
| Licensed under the Apache License, Version 2.0 (the "License"); | ||
| you may not use this file except in compliance with the License. | ||
| You may obtain a copy of the License at | ||
|
|
||
| http://www.apache.org/licenses/LICENSE-2.0 | ||
|
|
||
| Unless required by applicable law or agreed to in writing, software | ||
| distributed under the License is distributed on an "AS IS" BASIS, | ||
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| See the License for the specific language governing permissions and | ||
| limitations under the License. | ||
| */ | ||
|
|
||
| package cli | ||
|
|
||
| import "testing" | ||
|
|
||
| // A list filter names objects the way the store addresses them: PVC-X finds | ||
| // pvc-x, and my_res does not find My_Res, a definition of its own. | ||
| func TestListFiltersMatchByKey(t *testing.T) { | ||
| t.Parallel() | ||
|
|
||
| for _, tc := range []struct { | ||
| filter, value string | ||
| want bool | ||
| }{ | ||
| {"PVC-X", "pvc-x", true}, | ||
| {"Node-1", "node-1", true}, | ||
| {"my_res", "My_Res", false}, | ||
| {"My_Res", "My_Res", true}, | ||
| {"pvc-y", "pvc-x", false}, | ||
| } { | ||
| if got := matches([]string{tc.filter}, tc.value); got != tc.want { | ||
| t.Errorf("matches(%q, %q) = %v, want %v", tc.filter, tc.value, got, tc.want) | ||
| } | ||
| } | ||
| } | ||
|
|
||
| // A group's pool filter names pools the way the store addresses them. | ||
| func TestPoolFilterMatchesByKey(t *testing.T) { | ||
| t.Parallel() | ||
|
|
||
| if !matchesAny([]string{"ThinPool"}, "thinpool") { | ||
| t.Error("filter ThinPool does not admit pool thinpool") | ||
| } | ||
|
|
||
| if matchesAny([]string{"thin_pool"}, "Thin_Pool") { | ||
| t.Error("filter thin_pool admits Thin_Pool, another pool") | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,55 @@ | ||
| // SPDX-License-Identifier: Apache-2.0 | ||
|
|
||
| /* | ||
| Copyright 2026 Cozystack contributors. | ||
|
|
||
| Licensed under the Apache License, Version 2.0 (the "License"); | ||
| you may not use this file except in compliance with the License. | ||
| You may obtain a copy of the License at | ||
|
|
||
| http://www.apache.org/licenses/LICENSE-2.0 | ||
|
|
||
| Unless required by applicable law or agreed to in writing, software | ||
| distributed under the License is distributed on an "AS IS" BASIS, | ||
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| See the License for the specific language governing permissions and | ||
| limitations under the License. | ||
| */ | ||
|
|
||
| package cli | ||
|
|
||
| import ( | ||
| "testing" | ||
|
|
||
| apiv1 "github.com/cozystack/blockstor/pkg/api/v1" | ||
| "github.com/cozystack/blockstor/pkg/store" | ||
| ) | ||
|
|
||
| // The wire spells a replica's node as it was registered, Node-1, while the | ||
| // operator names the node node-1. The pool a restore or a create infers is | ||
| // the one of that node's own replica, or of a sibling, never the other way. | ||
| func TestPoolInferenceReadsTheNodeInAnotherSpelling(t *testing.T) { | ||
| t.Parallel() | ||
|
|
||
| st := store.NewInMemory() | ||
| ctx := t.Context() | ||
| run := &runContext{Store: st, Flags: &flagSet{Values: map[string]string{}}} | ||
|
|
||
| for _, node := range []string{"Node-1", "Node-2"} { | ||
| if err := st.Resources().Create(ctx, &apiv1.Resource{ | ||
| Name: "pvc-mix", | ||
| NodeName: node, | ||
| Props: map[string]string{storPoolNameProp: "pool-" + node}, | ||
| }); err != nil { | ||
| t.Fatalf("seed replica on %s: %v", node, err) | ||
| } | ||
| } | ||
|
|
||
| if pool, err := sourcePoolOn(ctx, run, "pvc-mix", "node-2"); err != nil || pool != "pool-Node-2" { | ||
| t.Errorf("sourcePoolOn(node-2) = %q, %v; want the pool of the replica on Node-2", pool, err) | ||
| } | ||
|
|
||
| if pool, err := resolveStorPool(ctx, run, "pvc-mix", "node-1"); err != nil || pool != "pool-Node-2" { | ||
| t.Errorf("resolveStorPool(node-1) = %q, %v; want the sibling's pool, not node-1's own", pool, err) | ||
| } | ||
| } |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Script executed:
Repository: cozystack/blockstor
Length of output: 5239
Script executed:
Repository: cozystack/blockstor
Length of output: 15108
Script executed:
Repository: cozystack/blockstor
Length of output: 2754
Script executed:
Repository: cozystack/blockstor
Length of output: 1861
Script executed:
Repository: cozystack/blockstor
Length of output: 201
Script executed:
sed -n '1555,1600p' pkg/linstormigrate/convert.goRepository: cozystack/blockstor
Length of output: 2201
Script executed:
Repository: cozystack/blockstor
Length of output: 2403
Script executed:
Repository: cozystack/blockstor
Length of output: 1057
Correct step 5 to name the RD, not the Resource.
The example at lines 54-55 says
<zpool>/<metadata.name of each Resource>_<vol %05d>. blockstor names the zvol after the resource definition, so this computes a name that does not exist. A Resource name includes the node, for examplepvc-a.node-1. The check then reports the realpvc-a_00000as missing. The runbook says to stop and rename the dataset or fix the converter, which can rename live data.Suggested fix