Message ID | 1489487010-17051-2-git-send-email-thuth@redhat.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
2017-03-14 11:23+0100, Thomas Huth: > To be able to do simple migration tests with kvm-unit-tests, too, > add a helper script that does all the necessary work: Start two > instances of QEMU (source and destination) with QMP sockets for > sending commands to them, then trigger the migration from one > instance to the other and finally signal the end of the migration > to the guest by injecting an NMI. > This helper script is now used automatically for powerpc tests > if the test is put into the "migration" group in the unittests.cfg > file. > > Signed-off-by: Thomas Huth <thuth@redhat.com> > --- > powerpc/run | 4 +++ > scripts/qemu-migration-helper.sh | 68 ++++++++++++++++++++++++++++++++++++++++ > scripts/runtime.bash | 3 ++ > 3 files changed, 75 insertions(+) > create mode 100755 scripts/qemu-migration-helper.sh > > diff --git a/powerpc/run b/powerpc/run > index 6269abb..f1528ed 100755 > --- a/powerpc/run > +++ b/powerpc/run > @@ -41,6 +41,10 @@ if ! $qemu -machine '?' 2>&1 | grep 'pseries' > /dev/null; then > exit 2 > fi > > +if [ "$MIGRATION" = "yes" ]; then > + qemu="scripts/qemu-migration-helper.sh $qemu" > +fi I think this script could be useful for other architectures as well ... what about adding migration_cmd to scripts/arch-run.bash migration_cmd () { if [ "$MIGRATION" = "yes" ]; then echo "scripts/qemu-migration-helper.sh" fi } and using only command="$(timeout_cmd) $(migration_cmd) $command" in arch scripts? > + > M='-machine pseries' > M+=",accel=$ACCEL" > command="$qemu -nodefaults $M -bios $FIRMWARE" > diff --git a/scripts/qemu-migration-helper.sh b/scripts/qemu-migration-helper.sh > new file mode 100755 > index 0000000..5842026 > --- /dev/null > +++ b/scripts/qemu-migration-helper.sh This doesn't seem to work with standalone tests, because they don't bundle scripts/qemu-migration-helper.sh ... Any reason why we couldn't turn it into a qemu-migration-helper () { ... } wrapper (likely inside scripts/arch-run.bash), so it would get sourced into the standalone test? > @@ -0,0 +1,68 @@ > +#!/bin/bash > +# This script runs two instances of QEMU and then migrates the guest from one > +# instance to the other. The end of the migration is signalled to the guest by > +# injecting an NMI. > + > +if ! command -v nc >/dev/null 2>&1; then > + echo "$0 needs nc (netcat)" > + exit 1 > +fi > + > +qemu=$1 > +shift > + > +if ! command -v "$qemu" >/dev/null 2>&1; then > + echo "The first parameter must be pointing to the QEMU executable" > + exit 1 > +fi > + > +migsock=`mktemp -u -t mig-helper-socket.XXXXXXXXXX` > +stdout1=`mktemp -t mig-helper-stdout1.XXXXXXXXXX` > +stdout2=`mktemp -t mig-helper-stdout2.XXXXXXXXXX` > +qmpout1=`mktemp -t mig-helper-qmpout1.XXXXXXXXXX` > +qmpout2=`mktemp -t mig-helper-qmpout2.XXXXXXXXXX` > +qmp1=`mktemp -u -t mig-helper-qmp1.XXXXXXXXXX` > +qmp2=`mktemp -u -t mig-helper-qmp2.XXXXXXXXXX` > + > +cleanup() > +{ > + rm -f ${stdout1} ${stdout2} ${migsock} > + rm -f ${qmpout1} ${qmpout2} ${qmp1} ${qmp2} > +} > +trap cleanup EXIT > + > +qmp_cmd() > +{ > + echo '{ "execute": "qmp_capabilities" }{ "execute":' "$2" '}' | nc -U $1 > +} > + > +$qemu $* -chardev socket,id=mon1,path=${qmp1},server,nowait \ I have a bad feeling about $*, please use "$@" instead. The difference can be seen in: # f () { g $*; } # g () {echo $#; } # f 1 2; f "1 2" 2 2 # f () { g "$@"; } # f 1 2; f "1 2" 2 1 > + -mon chardev=mon1,mode=control > ${stdout1} & > + > +$qemu $* -chardev socket,id=mon2,path=${qmp2},server,nowait \ > + -mon chardev=mon2,mode=control -incoming unix:${migsock} > ${stdout2} & > + > +# The test must prompt the user to migrate, so wait for the "migrate" keyword > +while ! grep -q -i "migrate" < ${stdout1} ; do > + sleep 1 > +done > + > +qmp_cmd ${qmp1} '"migrate", "arguments": { "uri": "unix:'${migsock}'" }' > ${qmpout1} > + > +# Wait for the migration to complete > +migstatus=`qmp_cmd ${qmp1} '"query-migrate"' | grep return` > +while ! grep -q '"completed"' <<<"$migstatus" ; do > + sleep 1 > + migstatus=`qmp_cmd ${qmp1} '"query-migrate"' | grep return` > + if grep -q '"failed"' <<<"$migstatus" ; then > + echo "ERROR: Migration failed." > + exit 1 > + fi > +done > +qmp_cmd ${qmp1} '"quit"'> ${qmpout1} 2>/dev/null > + > +qmp_cmd ${qmp2} '"inject-nmi"'> ${qmpout2} qmpout* seems unused ... couldn't we just redirect to /dev/null? > + > +wait > + > +cat ${stdout1} ${stdout2} The test might hang and we would never see its output ... I think that stdout1 could be duplicated using a crazy technique similar to what run_qemu() uses. And do we need to capture stdout2 at all? Thanks.
On 15.03.2017 17:36, Radim Krčmář wrote: > 2017-03-14 11:23+0100, Thomas Huth: >> To be able to do simple migration tests with kvm-unit-tests, too, >> add a helper script that does all the necessary work: Start two >> instances of QEMU (source and destination) with QMP sockets for >> sending commands to them, then trigger the migration from one >> instance to the other and finally signal the end of the migration >> to the guest by injecting an NMI. >> This helper script is now used automatically for powerpc tests >> if the test is put into the "migration" group in the unittests.cfg >> file. >> >> Signed-off-by: Thomas Huth <thuth@redhat.com> >> --- >> powerpc/run | 4 +++ >> scripts/qemu-migration-helper.sh | 68 ++++++++++++++++++++++++++++++++++++++++ >> scripts/runtime.bash | 3 ++ >> 3 files changed, 75 insertions(+) >> create mode 100755 scripts/qemu-migration-helper.sh >> >> diff --git a/powerpc/run b/powerpc/run >> index 6269abb..f1528ed 100755 >> --- a/powerpc/run >> +++ b/powerpc/run >> @@ -41,6 +41,10 @@ if ! $qemu -machine '?' 2>&1 | grep 'pseries' > /dev/null; then >> exit 2 >> fi >> >> +if [ "$MIGRATION" = "yes" ]; then >> + qemu="scripts/qemu-migration-helper.sh $qemu" >> +fi > > I think this script could be useful for other architectures as well ... > what about adding migration_cmd to scripts/arch-run.bash > > migration_cmd () > { > if [ "$MIGRATION" = "yes" ]; then > echo "scripts/qemu-migration-helper.sh" > fi > } > > and using only > > command="$(timeout_cmd) $(migration_cmd) $command" > > in arch scripts? Yes, sounds like a good idea, I'll change my patch accordingly. >> + >> M='-machine pseries' >> M+=",accel=$ACCEL" >> command="$qemu -nodefaults $M -bios $FIRMWARE" >> diff --git a/scripts/qemu-migration-helper.sh b/scripts/qemu-migration-helper.sh >> new file mode 100755 >> index 0000000..5842026 >> --- /dev/null >> +++ b/scripts/qemu-migration-helper.sh > > This doesn't seem to work with standalone tests, because they don't > bundle scripts/qemu-migration-helper.sh ... > > Any reason why we couldn't turn it into a > > qemu-migration-helper () { > ... > } > > wrapper (likely inside scripts/arch-run.bash), so it would get sourced > into the standalone test? Oh, well, I've completely forgot about that standalone test feature ... I'll have a look... >> @@ -0,0 +1,68 @@ >> +#!/bin/bash >> +# This script runs two instances of QEMU and then migrates the guest from one >> +# instance to the other. The end of the migration is signalled to the guest by >> +# injecting an NMI. >> + >> +if ! command -v nc >/dev/null 2>&1; then >> + echo "$0 needs nc (netcat)" >> + exit 1 >> +fi >> + >> +qemu=$1 >> +shift >> + >> +if ! command -v "$qemu" >/dev/null 2>&1; then >> + echo "The first parameter must be pointing to the QEMU executable" >> + exit 1 >> +fi >> + >> +migsock=`mktemp -u -t mig-helper-socket.XXXXXXXXXX` >> +stdout1=`mktemp -t mig-helper-stdout1.XXXXXXXXXX` >> +stdout2=`mktemp -t mig-helper-stdout2.XXXXXXXXXX` >> +qmpout1=`mktemp -t mig-helper-qmpout1.XXXXXXXXXX` >> +qmpout2=`mktemp -t mig-helper-qmpout2.XXXXXXXXXX` >> +qmp1=`mktemp -u -t mig-helper-qmp1.XXXXXXXXXX` >> +qmp2=`mktemp -u -t mig-helper-qmp2.XXXXXXXXXX` >> + >> +cleanup() >> +{ >> + rm -f ${stdout1} ${stdout2} ${migsock} >> + rm -f ${qmpout1} ${qmpout2} ${qmp1} ${qmp2} >> +} >> +trap cleanup EXIT >> + >> +qmp_cmd() >> +{ >> + echo '{ "execute": "qmp_capabilities" }{ "execute":' "$2" '}' | nc -U $1 >> +} >> + >> +$qemu $* -chardev socket,id=mon1,path=${qmp1},server,nowait \ > > I have a bad feeling about $*, please use "$@" instead. Sure, will do. >> + -mon chardev=mon1,mode=control > ${stdout1} & >> + >> +$qemu $* -chardev socket,id=mon2,path=${qmp2},server,nowait \ >> + -mon chardev=mon2,mode=control -incoming unix:${migsock} > ${stdout2} & >> + >> +# The test must prompt the user to migrate, so wait for the "migrate" keyword >> +while ! grep -q -i "migrate" < ${stdout1} ; do >> + sleep 1 >> +done >> + >> +qmp_cmd ${qmp1} '"migrate", "arguments": { "uri": "unix:'${migsock}'" }' > ${qmpout1} >> + >> +# Wait for the migration to complete >> +migstatus=`qmp_cmd ${qmp1} '"query-migrate"' | grep return` >> +while ! grep -q '"completed"' <<<"$migstatus" ; do >> + sleep 1 >> + migstatus=`qmp_cmd ${qmp1} '"query-migrate"' | grep return` >> + if grep -q '"failed"' <<<"$migstatus" ; then >> + echo "ERROR: Migration failed." >> + exit 1 >> + fi >> +done >> +qmp_cmd ${qmp1} '"quit"'> ${qmpout1} 2>/dev/null >> + >> +qmp_cmd ${qmp2} '"inject-nmi"'> ${qmpout2} > > qmpout* seems unused ... couldn't we just redirect to /dev/null? It's useful for debugging (you just got to make sure that it does not get deleted at the end)... but I could also set the variables to /dev/null instead, so the output gets written there by default. >> + >> +wait >> + >> +cat ${stdout1} ${stdout2} > > The test might hang and we would never see its output ... > I think that stdout1 could be duplicated using a crazy technique similar > to what run_qemu() uses. And do we need to capture stdout2 at all? At least on ppc, we need both outputs, since the return code of the test is finally passed via the console output there. But I'll see whether I can come up with something better here instead... Thanks for the review! Thomas
diff --git a/powerpc/run b/powerpc/run index 6269abb..f1528ed 100755 --- a/powerpc/run +++ b/powerpc/run @@ -41,6 +41,10 @@ if ! $qemu -machine '?' 2>&1 | grep 'pseries' > /dev/null; then exit 2 fi +if [ "$MIGRATION" = "yes" ]; then + qemu="scripts/qemu-migration-helper.sh $qemu" +fi + M='-machine pseries' M+=",accel=$ACCEL" command="$qemu -nodefaults $M -bios $FIRMWARE" diff --git a/scripts/qemu-migration-helper.sh b/scripts/qemu-migration-helper.sh new file mode 100755 index 0000000..5842026 --- /dev/null +++ b/scripts/qemu-migration-helper.sh @@ -0,0 +1,68 @@ +#!/bin/bash +# This script runs two instances of QEMU and then migrates the guest from one +# instance to the other. The end of the migration is signalled to the guest by +# injecting an NMI. + +if ! command -v nc >/dev/null 2>&1; then + echo "$0 needs nc (netcat)" + exit 1 +fi + +qemu=$1 +shift + +if ! command -v "$qemu" >/dev/null 2>&1; then + echo "The first parameter must be pointing to the QEMU executable" + exit 1 +fi + +migsock=`mktemp -u -t mig-helper-socket.XXXXXXXXXX` +stdout1=`mktemp -t mig-helper-stdout1.XXXXXXXXXX` +stdout2=`mktemp -t mig-helper-stdout2.XXXXXXXXXX` +qmpout1=`mktemp -t mig-helper-qmpout1.XXXXXXXXXX` +qmpout2=`mktemp -t mig-helper-qmpout2.XXXXXXXXXX` +qmp1=`mktemp -u -t mig-helper-qmp1.XXXXXXXXXX` +qmp2=`mktemp -u -t mig-helper-qmp2.XXXXXXXXXX` + +cleanup() +{ + rm -f ${stdout1} ${stdout2} ${migsock} + rm -f ${qmpout1} ${qmpout2} ${qmp1} ${qmp2} +} +trap cleanup EXIT + +qmp_cmd() +{ + echo '{ "execute": "qmp_capabilities" }{ "execute":' "$2" '}' | nc -U $1 +} + +$qemu $* -chardev socket,id=mon1,path=${qmp1},server,nowait \ + -mon chardev=mon1,mode=control > ${stdout1} & + +$qemu $* -chardev socket,id=mon2,path=${qmp2},server,nowait \ + -mon chardev=mon2,mode=control -incoming unix:${migsock} > ${stdout2} & + +# The test must prompt the user to migrate, so wait for the "migrate" keyword +while ! grep -q -i "migrate" < ${stdout1} ; do + sleep 1 +done + +qmp_cmd ${qmp1} '"migrate", "arguments": { "uri": "unix:'${migsock}'" }' > ${qmpout1} + +# Wait for the migration to complete +migstatus=`qmp_cmd ${qmp1} '"query-migrate"' | grep return` +while ! grep -q '"completed"' <<<"$migstatus" ; do + sleep 1 + migstatus=`qmp_cmd ${qmp1} '"query-migrate"' | grep return` + if grep -q '"failed"' <<<"$migstatus" ; then + echo "ERROR: Migration failed." + exit 1 + fi +done +qmp_cmd ${qmp1} '"quit"'> ${qmpout1} 2>/dev/null + +qmp_cmd ${qmp2} '"inject-nmi"'> ${qmpout2} + +wait + +cat ${stdout1} ${stdout2} diff --git a/scripts/runtime.bash b/scripts/runtime.bash index 9c1bc3b..f58eb4e 100644 --- a/scripts/runtime.bash +++ b/scripts/runtime.bash @@ -98,6 +98,9 @@ function run() } cmdline=$(get_cmdline $kernel) + if grep -qw "migration" <<<$groups ; then + cmdline="MIGRATION=yes $cmdline" + fi if [ "$verbose" = "yes" ]; then echo $cmdline fi
To be able to do simple migration tests with kvm-unit-tests, too, add a helper script that does all the necessary work: Start two instances of QEMU (source and destination) with QMP sockets for sending commands to them, then trigger the migration from one instance to the other and finally signal the end of the migration to the guest by injecting an NMI. This helper script is now used automatically for powerpc tests if the test is put into the "migration" group in the unittests.cfg file. Signed-off-by: Thomas Huth <thuth@redhat.com> --- powerpc/run | 4 +++ scripts/qemu-migration-helper.sh | 68 ++++++++++++++++++++++++++++++++++++++++ scripts/runtime.bash | 3 ++ 3 files changed, 75 insertions(+) create mode 100755 scripts/qemu-migration-helper.sh