Skip to content

Commit b50f2f8

Browse files
author
Rohit-PX
committed
integrationt test for sticky vol failover failback
Signed-off-by: Rohit-PX <rkulkarni@purestorage.com>
1 parent 2a02115 commit b50f2f8

8 files changed

Lines changed: 197 additions & 10 deletions

File tree

test/integration_test/migration_failover_failback_test.go

Lines changed: 71 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,14 @@ package integrationtest
66
import (
77
"fmt"
88
"testing"
9+
"time"
910

1011
"github.com/libopenstorage/stork/pkg/apis/stork/v1alpha1"
1112
"github.com/portworx/sched-ops/k8s/core"
13+
storkops "github.com/portworx/sched-ops/k8s/stork"
1214
"github.com/portworx/sched-ops/task"
1315
"github.com/portworx/torpedo/drivers/scheduler"
16+
"github.com/sirupsen/logrus"
1417
"github.com/stretchr/testify/require"
1518
v1 "k8s.io/api/core/v1"
1619
"k8s.io/apimachinery/pkg/api/errors"
@@ -54,10 +57,11 @@ func testMigrationFailoverFailback(t *testing.T) {
5457

5558
t.Run("vanillaFailoverAndFailbackMigrationTest", vanillaFailoverAndFailbackMigrationTest)
5659
t.Run("rancherFailoverAndFailbackMigrationTest", rancherFailoverAndFailbackMigrationTest)
60+
t.Run("stickyFlagFailoverAndFailbackMigrationTest", stickyFlagFailoverAndFailbackMigrationTest)
5761
}
5862

5963
func vanillaFailoverAndFailbackMigrationTest(t *testing.T) {
60-
failoverAndFailbackMigrationTest(t)
64+
failoverAndFailbackMigrationTest(t, "mysql-enc-pvc", "mysql-migration-failover-failback", true)
6165
}
6266

6367
func rancherFailoverAndFailbackMigrationTest(t *testing.T) {
@@ -105,20 +109,22 @@ func rancherFailoverAndFailbackMigrationTest(t *testing.T) {
105109

106110
scaleFactor := testMigrationFailover(t, preMigrationCtx, ctxs, "", appKey, instanceID)
107111

108-
testMigrationFailback(t, preMigrationCtx, ctxs, scaleFactor, projectIDMappingsReverse, appKey, instanceID)
112+
testMigrationFailback(t, preMigrationCtx, ctxs, scaleFactor, projectIDMappingsReverse, appKey, instanceID, true)
109113
}
110114

111-
func failoverAndFailbackMigrationTest(t *testing.T) {
115+
func stickyFlagFailoverAndFailbackMigrationTest(t *testing.T) {
116+
failoverAndFailbackMigrationTest(t, "mysql-sticky", "mysql-migration-sticky", false)
117+
}
118+
119+
func failoverAndFailbackMigrationTest(t *testing.T, appKey, migrationKey string, failbackSuccessExpected bool) {
112120

113-
appKey := "mysql-enc-pvc"
114-
instanceID := "mysql-migration-failover-failback"
115121
// Migrate the resources
116122
ctxs, preMigrationCtx := triggerMigration(
117123
t,
118-
instanceID,
124+
migrationKey,
119125
appKey,
120126
nil,
121-
[]string{instanceID},
127+
[]string{migrationKey},
122128
true,
123129
false,
124130
false,
@@ -150,9 +156,9 @@ func failoverAndFailbackMigrationTest(t *testing.T) {
150156
// validate the migration summary based on the application specs that were deployed by the test
151157
validateMigrationSummary(t, preMigrationCtx, expectedResources, expectedVolumes, migrationObj.Name, migrationObj.Namespace)
152158

153-
scaleFactor := testMigrationFailover(t, preMigrationCtx, ctxs, "", appKey, instanceID)
159+
scaleFactor := testMigrationFailover(t, preMigrationCtx, ctxs, "", appKey, migrationKey)
154160

155-
testMigrationFailback(t, preMigrationCtx, ctxs, scaleFactor, "", appKey, instanceID)
161+
testMigrationFailback(t, preMigrationCtx, ctxs, scaleFactor, "", appKey, migrationKey, failbackSuccessExpected)
156162
}
157163

158164
func testMigrationFailover(
@@ -242,6 +248,7 @@ func testMigrationFailback(
242248
scaleFactor map[string]int32,
243249
projectIDMappings string,
244250
appKey, instanceID string,
251+
failbackSuccessExpected bool,
245252
) {
246253
// Failback the application
247254
// Trigger a reverse migration
@@ -251,6 +258,8 @@ func testMigrationFailback(
251258
require.NoError(t, err, "Error scheduling task")
252259
require.Equal(t, 1, len(ctxsReverse), "Only one task should have started")
253260

261+
appCtx := ctxsReverse[0]
262+
254263
err = schedulerDriver.WaitForRunning(ctxsReverse[0], defaultWaitTimeout, defaultWaitInterval)
255264
require.NoError(t, err, "Error waiting for app to get to running state")
256265

@@ -265,6 +274,50 @@ func testMigrationFailback(
265274
scheduler.ScheduleOptions{AppKeys: []string{instanceID}})
266275
require.NoError(t, err, "Error scheduling migration specs")
267276

277+
if !failbackSuccessExpected {
278+
// In case of sticky volumes migration failure is expected, so will update volume and trigger migration again
279+
err = schedulerDriver.WaitForRunning(ctxsReverse[0], defaultWaitTimeout/10, defaultWaitInterval)
280+
require.Error(t, err, "Expected failback migration to fail")
281+
282+
// Get volumes for this migration on source cluster and update sticky flag
283+
err = setSourceKubeConfig()
284+
require.NoError(t, err, "Error resetting source config, for updating sticky volume")
285+
286+
vols, err := schedulerDriver.GetVolumes(appCtx)
287+
require.NoError(t, err, "Error getting volumes for app")
288+
for _, v := range vols {
289+
err = volumeDriver.UpdateStickyFlag(v.ID, "off")
290+
require.NoError(t, err, "Error updating sticky flag for volumes %s", v.Name)
291+
}
292+
time.Sleep(3 * time.Minute)
293+
294+
// Trigger migration on destination cluster again
295+
err = setDestinationKubeConfig()
296+
require.NoError(t, err, "Error setting destination config after updating sticky volume")
297+
298+
var failedMigrationObj *v1alpha1.Migration
299+
var ok bool
300+
for _, specObj := range ctxsReverse[0].App.SpecList {
301+
if failedMigrationObj, ok = specObj.(*v1alpha1.Migration); ok {
302+
break
303+
}
304+
}
305+
failedMigrationObj, err = storkops.Instance().GetMigration(failedMigrationObj.Name, failedMigrationObj.Namespace)
306+
require.NoError(t, err, "Error getting the failed migration")
307+
logrus.Infof("Failed migration object found: %s in namespace: %s. Status: %s", failedMigrationObj.Name, failedMigrationObj.Namespace, failedMigrationObj.Status.Status)
308+
309+
err = deleteMigrations([]*v1alpha1.Migration{failedMigrationObj})
310+
require.NoError(t, err, "error in deleting failed migrations.")
311+
312+
// apply migration specs again, it should pass this time
313+
err = schedulerDriver.AddTasks(ctxsReverse[0],
314+
scheduler.ScheduleOptions{AppKeys: []string{instanceID}})
315+
require.NoError(t, err, "Error scheduling migration specs")
316+
317+
err = schedulerDriver.WaitForRunning(ctxsReverse[0], defaultWaitTimeout, defaultWaitInterval)
318+
require.NoError(t, err, "Error waiting for migration to complete post sticky flag update")
319+
}
320+
268321
err = schedulerDriver.WaitForRunning(ctxsReverse[0], defaultWaitTimeout, defaultWaitInterval)
269322
require.NoError(t, err, "Error waiting for migration to complete")
270323

@@ -322,8 +375,16 @@ func testMigrationFailback(
322375
require.Equal(t, projectValue, "project-A")
323376
}
324377
}
325-
326378
destroyAndWait(t, []*scheduler.Context{postMigrationCtx})
379+
destroyAndWait(t, ctxs)
380+
381+
err = setDestinationKubeConfig()
382+
require.NoError(t, err, "Error resetting remote config")
383+
destroyAndWait(t, ctxsReverse)
384+
385+
err = setSourceKubeConfig()
386+
require.NoError(t, err, "Error resetting remote config")
387+
327388
}
328389

329390
// The below two functions are currently not invoked during the tests since the namespaceSelector
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
apiVersion: stork.libopenstorage.org/v1alpha1
2+
kind: Migration
3+
metadata:
4+
name: mysql-sticky-migration
5+
spec:
6+
# This should be the name of the cluster pair
7+
clusterPair: remoteclusterpair
8+
# If set to false this will migrate only the volumes. No PVCs, apps, etc will be migrated
9+
includeResources: true
10+
# If set to false, the deployments and stateful set replicas will be set to 0 on the destination. There will be an annotation with "stork.openstorage.org/migrationReplicas" to store the replica count from the source
11+
startApplications: false
12+
# List of namespaces to migrate
13+
namespaces:
14+
- mysql-sticky-mysql-migration-sticky
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
kind: StorageClass
2+
apiVersion: storage.k8s.io/v1
3+
metadata:
4+
name: mysql-sc
5+
provisioner: kubernetes.io/aws-ebs
6+
parameters:
7+
type: gp2
8+
reclaimPolicy: Delete
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
apiVersion: storage.k8s.io/v1
2+
kind: StorageClass
3+
metadata:
4+
name: mysql-sc
5+
provisioner: kubernetes.io/azure-disk
6+
parameters:
7+
skuName: Standard_LRS
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
apiVersion: storage.k8s.io/v1
2+
kind: StorageClass
3+
metadata:
4+
name: mysql-sc
5+
parameters:
6+
type: pd-standard
7+
provisioner: kubernetes.io/gce-pd
8+
reclaimPolicy: Delete
9+
volumeBindingMode: Immediate
10+
allowVolumeExpansion: true
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
kind: StorageClass
2+
apiVersion: storage.k8s.io/v1
3+
metadata:
4+
name: mysql-sc
5+
provisioner: linstor.csi.linbit.com
6+
allowVolumeExpansion: true
7+
reclaimPolicy: Delete
8+
parameters:
9+
autoPlace: "2"
10+
storagePool: sda
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
apiVersion: apps/v1
2+
kind: StatefulSet
3+
metadata:
4+
name: mysql
5+
labels:
6+
app: mysql
7+
spec:
8+
serviceName: mysql-service
9+
replicas: 1
10+
selector:
11+
matchLabels:
12+
app: mysql
13+
version: "1"
14+
template:
15+
metadata:
16+
labels:
17+
app: mysql
18+
version: "1"
19+
spec:
20+
schedulerName: stork
21+
containers:
22+
- image: mysql:5.6
23+
name: mysql
24+
env:
25+
- name: MYSQL_ROOT_PASSWORD
26+
value: password
27+
ports:
28+
- containerPort: 3306
29+
livenessProbe:
30+
exec:
31+
command: ["sh", "-c", "mysqladmin -u root -p$MYSQL_ROOT_PASSWORD ping"]
32+
initialDelaySeconds: 70
33+
periodSeconds: 10
34+
timeoutSeconds: 5
35+
readinessProbe:
36+
exec:
37+
command: ["sh", "-c", "mysql -u root -p$MYSQL_ROOT_PASSWORD -e \"select 1\""]
38+
initialDelaySeconds: 60
39+
periodSeconds: 10
40+
timeoutSeconds: 5
41+
volumeMounts:
42+
- name: mysql-data
43+
mountPath: /var/lib/mysql
44+
volumeClaimTemplates:
45+
- metadata:
46+
name: mysql-data
47+
annotations:
48+
volume.beta.kubernetes.io/storage-class: mysql-sticky-sc
49+
px/secret-name: volume-secrets
50+
px/secret-namespace: kube-system
51+
px/secret-key: mysql-secret
52+
spec:
53+
accessModes: [ "ReadWriteOnce" ]
54+
resources:
55+
requests:
56+
storage: 8Gi
57+
---
58+
apiVersion: v1
59+
kind: Service
60+
metadata:
61+
name: mysql-service
62+
labels:
63+
app: mysql
64+
spec:
65+
selector:
66+
app: mysql
67+
ports:
68+
- name: transport
69+
port: 3306
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
kind: StorageClass
2+
apiVersion: storage.k8s.io/v1
3+
metadata:
4+
name: mysql-sticky-sc
5+
provisioner: kubernetes.io/portworx-volume
6+
parameters:
7+
repl: "2"
8+
sticky: "true"

0 commit comments

Comments
 (0)