add multi-instance Queue Managers (#307)
* Initial code to implement multi-instance queue manager * alter default mqsc to prevent race between listeners on standby startup * Updates to multi-instance queue manager code * initial multi instance test * Multi-instance code improvements * Multi instance fixes and first test * configure queue manager * Add mirror log filtering for mult-instance QMs * Add log message for multi-instance enabled * Improvements to container runtime logging * refactor test * Test active standby switch * Improve createQueueManager function * Test multi instance race * wait * multi instance mount tests * skip race test * mount tests * no mount test * single instance split mount tests * readiness check * More updates for handling standby queue manager * Improve standby checks * Minor fixes to miqm * Fix logging of JSON errors * Update copyrights * Fix log includes
This commit is contained in:
committed by
Arthur Barr
parent
63af43f19d
commit
6c72c894f7
234
test/docker/mq_multi_instance_test.go
Normal file
234
test/docker/mq_multi_instance_test.go
Normal file
@@ -0,0 +1,234 @@
|
||||
/*
|
||||
© Copyright IBM Corporation 2019
|
||||
|
||||
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 main
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/docker/docker/client"
|
||||
)
|
||||
|
||||
var miEnv = []string{
|
||||
"LICENSE=accept",
|
||||
"MQ_QMGR_NAME=QM1",
|
||||
"MQ_MULTI_INSTANCE=true",
|
||||
}
|
||||
|
||||
// TestMultiInstanceStartStop creates 2 containers in a multi instance queue manager configuration
|
||||
// and starts/stop them checking we always have an active and standby
|
||||
func TestMultiInstanceStartStop(t *testing.T) {
|
||||
cli, err := client.NewEnvClient()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
err, qm1aId, qm1bId, volumes := configureMultiInstance(t, cli)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for _, volume := range volumes {
|
||||
defer removeVolume(t, cli, volume)
|
||||
}
|
||||
defer cleanContainer(t, cli, qm1aId)
|
||||
defer cleanContainer(t, cli, qm1bId)
|
||||
|
||||
waitForReady(t, cli, qm1aId)
|
||||
waitForReady(t, cli, qm1bId)
|
||||
|
||||
err, active, standby := getActiveStandbyQueueManager(t, cli, qm1aId, qm1bId)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
killContainer(t, cli, active, "SIGTERM")
|
||||
time.Sleep(2 * time.Second)
|
||||
|
||||
if status := getQueueManagerStatus(t, cli, standby, "QM1"); strings.Compare(status, "Running") != 0 {
|
||||
t.Fatalf("Expected QM1 to be running as active queue manager, dspmq returned status of %v", status)
|
||||
}
|
||||
|
||||
startContainer(t, cli, qm1aId)
|
||||
waitForReady(t, cli, qm1aId)
|
||||
|
||||
err, _, _ = getActiveStandbyQueueManager(t, cli, qm1aId, qm1bId)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// TestMultiInstanceContainerStop starts 2 containers in a multi instance queue manager configuration,
|
||||
// stops the active queue manager, then checks to ensure the backup queue manager becomes active
|
||||
func TestMultiInstanceContainerStop(t *testing.T) {
|
||||
cli, err := client.NewEnvClient()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
err, qm1aId, qm1bId, volumes := configureMultiInstance(t, cli)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for _, volume := range volumes {
|
||||
defer removeVolume(t, cli, volume)
|
||||
}
|
||||
defer cleanContainer(t, cli, qm1aId)
|
||||
defer cleanContainer(t, cli, qm1bId)
|
||||
|
||||
waitForReady(t, cli, qm1aId)
|
||||
waitForReady(t, cli, qm1bId)
|
||||
|
||||
err, active, standby := getActiveStandbyQueueManager(t, cli, qm1aId, qm1bId)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
stopContainer(t, cli, active)
|
||||
|
||||
if status := getQueueManagerStatus(t, cli, standby, "QM1"); strings.Compare(status, "Running") != 0 {
|
||||
t.Fatalf("Expected QM1 to be running as active queue manager, dspmq returned status of %v", status)
|
||||
}
|
||||
}
|
||||
|
||||
// TestMultiInstanceRace starts 2 containers in separate goroutines in a multi instance queue manager
|
||||
// configuration, then checks to ensure that both an active and standby queue manager have been started
|
||||
func TestMultiInstanceRace(t *testing.T) {
|
||||
t.Skipf("Skipping %v until file lock is implemented", t.Name())
|
||||
|
||||
cli, err := client.NewEnvClient()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
qmsharedlogs := createVolume(t, cli, "qmsharedlogs")
|
||||
defer removeVolume(t, cli, qmsharedlogs.Name)
|
||||
qmshareddata := createVolume(t, cli, "qmshareddata")
|
||||
defer removeVolume(t, cli, qmshareddata.Name)
|
||||
|
||||
qmsChannel := make(chan QMChan)
|
||||
|
||||
go singleMultiInstanceQueueManager(t, cli, qmsharedlogs.Name, qmshareddata.Name, qmsChannel)
|
||||
go singleMultiInstanceQueueManager(t, cli, qmsharedlogs.Name, qmshareddata.Name, qmsChannel)
|
||||
|
||||
qm1a := <-qmsChannel
|
||||
if qm1a.Error != nil {
|
||||
t.Fatal(qm1a.Error)
|
||||
}
|
||||
|
||||
qm1b := <-qmsChannel
|
||||
if qm1b.Error != nil {
|
||||
t.Fatal(qm1b.Error)
|
||||
}
|
||||
|
||||
qm1aId, qm1aData := qm1a.QMId, qm1a.QMData
|
||||
qm1bId, qm1bData := qm1b.QMId, qm1b.QMData
|
||||
|
||||
defer removeVolume(t, cli, qm1aData)
|
||||
defer removeVolume(t, cli, qm1bData)
|
||||
defer cleanContainer(t, cli, qm1aId)
|
||||
defer cleanContainer(t, cli, qm1bId)
|
||||
|
||||
waitForReady(t, cli, qm1aId)
|
||||
waitForReady(t, cli, qm1bId)
|
||||
|
||||
err, _, _ = getActiveStandbyQueueManager(t, cli, qm1aId, qm1bId)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
// TestMultiInstanceNoSharedMounts starts 2 multi instance queue managers without providing shared log/data
|
||||
// mounts, then checks to ensure that the container terminates with the expected message
|
||||
func TestMultiInstanceNoSharedMounts(t *testing.T) {
|
||||
t.Parallel()
|
||||
cli, err := client.NewEnvClient()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err, qm1aId, qm1aData := startMultiVolumeQueueManager(t, cli, true, "", "", miEnv)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
defer removeVolume(t, cli, qm1aData)
|
||||
defer cleanContainer(t, cli, qm1aId)
|
||||
|
||||
waitForTerminationMessage(t, cli, qm1aId, "Missing required mount '/mnt/mqm-log'", 30*time.Second)
|
||||
}
|
||||
|
||||
// TestMultiInstanceNoSharedLogs starts 2 multi instance queue managers without providing a shared log
|
||||
// mount, then checks to ensure that the container terminates with the expected message
|
||||
func TestMultiInstanceNoSharedLogs(t *testing.T) {
|
||||
cli, err := client.NewEnvClient()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
qmshareddata := createVolume(t, cli, "qmshareddata")
|
||||
defer removeVolume(t, cli, qmshareddata.Name)
|
||||
|
||||
err, qm1aId, qm1aData := startMultiVolumeQueueManager(t, cli, true, "", qmshareddata.Name, miEnv)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
defer removeVolume(t, cli, qm1aData)
|
||||
defer cleanContainer(t, cli, qm1aId)
|
||||
|
||||
waitForTerminationMessage(t, cli, qm1aId, "Missing required mount '/mnt/mqm-log'", 30*time.Second)
|
||||
}
|
||||
|
||||
// TestMultiInstanceNoSharedData starts 2 multi instance queue managers without providing a shared data
|
||||
// mount, then checks to ensure that the container terminates with the expected message
|
||||
func TestMultiInstanceNoSharedData(t *testing.T) {
|
||||
cli, err := client.NewEnvClient()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
qmsharedlogs := createVolume(t, cli, "qmsharedlogs")
|
||||
defer removeVolume(t, cli, qmsharedlogs.Name)
|
||||
|
||||
err, qm1aId, qm1aData := startMultiVolumeQueueManager(t, cli, true, qmsharedlogs.Name, "", miEnv)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
defer removeVolume(t, cli, qm1aData)
|
||||
defer cleanContainer(t, cli, qm1aId)
|
||||
|
||||
waitForTerminationMessage(t, cli, qm1aId, "Missing required mount '/mnt/mqm-data'", 30*time.Second)
|
||||
}
|
||||
|
||||
// TestMultiInstanceNoMounts starts 2 multi instance queue managers without providing a shared data
|
||||
// mount, then checks to ensure that the container terminates with the expected message
|
||||
func TestMultiInstanceNoMounts(t *testing.T) {
|
||||
cli, err := client.NewEnvClient()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err, qm1aId, qm1aData := startMultiVolumeQueueManager(t, cli, false, "", "", miEnv)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
defer removeVolume(t, cli, qm1aData)
|
||||
defer cleanContainer(t, cli, qm1aId)
|
||||
|
||||
waitForTerminationMessage(t, cli, qm1aId, "Missing required mount '/mnt/mqm'", 30*time.Second)
|
||||
}
|
||||
Reference in New Issue
Block a user