Skip to content

Commit 1829c49

Browse files
PWX-37650: Supports adding the pod name as a locator label for clone/snap restore (#2452)
Signed-off-by: Adam Krpan <akrpan@purestorage.com>
1 parent c0c3096 commit 1829c49

File tree

5 files changed

+154
-4
lines changed

5 files changed

+154
-4
lines changed

api/api.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1332,6 +1332,14 @@ func (v *VolumeSpec) IsNFSProxyVolume() bool {
13321332
return v.GetProxySpec() != nil && v.GetProxySpec().NfsSpec != nil
13331333
}
13341334

1335+
// GetFADAPodName returns the FlashArray Pod name specified in the Pure Block spec, or empty if any fields are unspecified
1336+
func (v *VolumeSpec) GetFADAPodName() string {
1337+
if v.GetProxySpec() != nil && v.GetProxySpec().PureBlockSpec != nil {
1338+
return v.GetProxySpec().PureBlockSpec.PodName
1339+
}
1340+
return ""
1341+
}
1342+
13351343
// GetCloneCreatorOwnership returns the appropriate ownership for the
13361344
// new snapshot and if an update is required
13371345
func (v *VolumeSpec) GetCloneCreatorOwnership(ctx context.Context) (*Ownership, bool) {

api/server/sdk/volume_ops.go

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@ import (
3636
"google.golang.org/grpc/status"
3737
)
3838

39+
// FADAPodLabelKey is a label added to volume locators in the case of FADA volume clone/snap restore
40+
const FADAPodLabelKey = "pure-pod-name" // Used to plumb in the pod name for volume cloning
41+
3942
// When create is called for an existing volume, this function is called to make sure
4043
// the SDK only returns that the volume is ready when the status is UP
4144
func (s *VolumeServer) waitForVolumeReady(ctx context.Context, id string) (*api.Volume, error) {
@@ -106,7 +109,6 @@ func (s *VolumeServer) create(
106109
spec *api.VolumeSpec,
107110
additionalCloneLabels map[string]string,
108111
) (string, error) {
109-
110112
// Check if the volume has already been created or is in process of creation
111113
volName := locator.GetName()
112114
v, err := util.VolumeFromName(ctx, s.driver(ctx), volName)
@@ -171,8 +173,18 @@ func (s *VolumeServer) create(
171173
}
172174

173175
// Create a snapshot from the parent
176+
// Only include the FADA pod label
177+
var labels map[string]string = nil
178+
if locator.GetVolumeLabels() != nil {
179+
if pod, ok := locator.GetVolumeLabels()[FADAPodLabelKey]; ok {
180+
labels = map[string]string{
181+
FADAPodLabelKey: pod,
182+
}
183+
}
184+
}
174185
id, err = s.driver(ctx).Snapshot(ctx, parent.GetId(), false, &api.VolumeLocator{
175-
Name: volName,
186+
Name: volName,
187+
VolumeLabels: labels,
176188
}, false)
177189
if err != nil {
178190
if err == kvdb.ErrNotFound {
@@ -335,7 +347,8 @@ func (s *VolumeServer) Clone(
335347
}
336348

337349
locator := &api.VolumeLocator{
338-
Name: req.GetName(),
350+
Name: req.GetName(),
351+
VolumeLabels: req.GetAdditionalLabels(),
339352
}
340353
source := &api.Source{
341354
Parent: req.GetParentId(),

api/spec/spec_handler.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -640,6 +640,14 @@ func (d *specHandler) UpdateSpecFromOpts(opts map[string]string, spec *api.Volum
640640
case api.SpecBackendVolName:
641641
volName := v
642642
pureBackendVolName = &volName
643+
case api.SpecPurePodName:
644+
if spec.ProxySpec == nil {
645+
spec.ProxySpec = &api.ProxySpec{}
646+
}
647+
if spec.ProxySpec.PureBlockSpec == nil {
648+
spec.ProxySpec.PureBlockSpec = &api.PureBlockSpec{}
649+
}
650+
spec.ProxySpec.PureBlockSpec.PodName = v
643651
case api.SpecPureFileExportRules:
644652
if spec.ProxySpec == nil {
645653
spec.ProxySpec = &api.ProxySpec{}

csi/controller.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -614,10 +614,14 @@ func (s *OsdCsiServer) CreateVolume(
614614
}
615615
newVolumeId = createResp.VolumeId
616616
} else {
617+
clonedMetadata := getClonedPVCMetadata(locator)
618+
if spec.GetFADAPodName() != "" {
619+
clonedMetadata[sdk.FADAPodLabelKey] = spec.GetFADAPodName()
620+
}
617621
cloneResp, err := volumes.Clone(ctx, &api.SdkVolumeCloneRequest{
618622
Name: req.GetName(),
619623
ParentId: source.Parent,
620-
AdditionalLabels: getClonedPVCMetadata(locator),
624+
AdditionalLabels: clonedMetadata,
621625
})
622626
if err != nil {
623627
return nil, err

csi/controller_test.go

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import (
3333
"github.com/golang/protobuf/ptypes/timestamp"
3434
"github.com/libopenstorage/openstorage/api"
3535
"github.com/libopenstorage/openstorage/api/mock"
36+
"github.com/libopenstorage/openstorage/api/server/sdk"
3637
"github.com/libopenstorage/openstorage/api/spec"
3738
authsecrets "github.com/libopenstorage/openstorage/pkg/auth/secrets"
3839
mockLoadBalancer "github.com/libopenstorage/openstorage/pkg/loadbalancer/mock"
@@ -1983,6 +1984,122 @@ func TestControllerCreateVolumeFromSnapshot(t *testing.T) {
19831984
assert.Equal(t, mockParentID, volumeInfo.GetVolumeContext()[api.SpecParent])
19841985
}
19851986

1987+
func TestControllerCreateVolumeFromSnapshotFADAPod(t *testing.T) {
1988+
// Create server and client connection
1989+
s := newTestServer(t)
1990+
defer s.Stop()
1991+
c := csi.NewControllerClient(s.Conn())
1992+
s.mockClusterEnumerateNode(t, "node-1")
1993+
// Setup request
1994+
mockParentID := "parendId"
1995+
name := "myvol"
1996+
pod := "mypod"
1997+
size := int64(1234)
1998+
req := &csi.CreateVolumeRequest{
1999+
Name: name,
2000+
VolumeCapabilities: []*csi.VolumeCapability{
2001+
{},
2002+
},
2003+
CapacityRange: &csi.CapacityRange{
2004+
RequiredBytes: size,
2005+
},
2006+
VolumeContentSource: &csi.VolumeContentSource{
2007+
Type: &csi.VolumeContentSource_Snapshot{
2008+
Snapshot: &csi.VolumeContentSource_SnapshotSource{
2009+
SnapshotId: mockParentID,
2010+
},
2011+
},
2012+
},
2013+
Secrets: map[string]string{authsecrets.SecretTokenKey: systemUserToken},
2014+
Parameters: map[string]string{
2015+
api.SpecPurePodName: pod,
2016+
},
2017+
}
2018+
2019+
// Setup mock functions
2020+
id := "myid"
2021+
snapID := id + "-snap"
2022+
gomock.InOrder(
2023+
2024+
// First check on parent
2025+
s.MockDriver().
2026+
EXPECT().
2027+
Enumerate(&api.VolumeLocator{
2028+
VolumeIds: []string{mockParentID},
2029+
}, nil).
2030+
Return([]*api.Volume{{Id: mockParentID}}, nil).
2031+
Times(1),
2032+
2033+
// VolFromName (name)
2034+
s.MockDriver().
2035+
EXPECT().
2036+
Inspect(gomock.Any(), []string{name}).
2037+
Return(nil, fmt.Errorf("not found")).
2038+
Times(1),
2039+
2040+
s.MockDriver().
2041+
EXPECT().
2042+
Enumerate(gomock.Any(), nil).
2043+
Return(nil, fmt.Errorf("not found")).
2044+
Times(1),
2045+
2046+
//VolFromName parent
2047+
s.MockDriver().
2048+
EXPECT().
2049+
Inspect(gomock.Any(), gomock.Any()).
2050+
Return(
2051+
[]*api.Volume{{
2052+
Id: mockParentID,
2053+
}}, nil).
2054+
Times(1),
2055+
2056+
// create
2057+
s.MockDriver().
2058+
EXPECT().
2059+
Snapshot(gomock.Any(), gomock.Any(), gomock.Any(), &api.VolumeLocator{Name: name, VolumeLabels: map[string]string{sdk.FADAPodLabelKey: pod}}, gomock.Any()).
2060+
Return(snapID, nil).
2061+
Times(1),
2062+
s.MockDriver().
2063+
EXPECT().
2064+
Enumerate(&api.VolumeLocator{
2065+
VolumeIds: []string{snapID},
2066+
}, nil).
2067+
Return([]*api.Volume{
2068+
{
2069+
Id: id,
2070+
Source: &api.Source{Parent: mockParentID},
2071+
},
2072+
}, nil).
2073+
Times(2),
2074+
2075+
s.MockDriver().
2076+
EXPECT().
2077+
Set(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).
2078+
Return(nil).
2079+
Times(1),
2080+
2081+
s.MockDriver().
2082+
EXPECT().
2083+
Enumerate(gomock.Any(), nil).
2084+
Return([]*api.Volume{
2085+
{
2086+
Id: id,
2087+
Source: &api.Source{Parent: mockParentID},
2088+
},
2089+
}, nil).
2090+
Times(1),
2091+
)
2092+
2093+
r, err := c.CreateVolume(context.Background(), req)
2094+
assert.Nil(t, err)
2095+
assert.NotNil(t, r)
2096+
volumeInfo := r.GetVolume()
2097+
2098+
assert.Equal(t, id, volumeInfo.GetVolumeId())
2099+
assert.NotEqual(t, "true", volumeInfo.GetVolumeContext()[api.SpecSharedv4])
2100+
assert.Equal(t, mockParentID, volumeInfo.GetVolumeContext()[api.SpecParent])
2101+
}
2102+
19862103
func TestControllerCreateVolumeSnapshotThroughParameters(t *testing.T) {
19872104
// Create server and client connection
19882105
s := newTestServer(t)

0 commit comments

Comments
 (0)