ICTSC2018 本戦 問題解説: Upgrade QEMU; Ubuntu 16.04 -> 18.04

問題文

Ubuntu 16.04 にて、以下の操作で QEMU の API である QMP を使ってディスクの追加を行っていたが、 Ubuntu 18.04 では動作しなかった。 Ubuntu 18.04で同じ動作をするように QMP の操作を見直してほしい。
$ cd
$ qemu-system-x86_64 -uuid c01769df-766c-49e3-9c8c-d148e9557975 -name guest=test,debug-threads=on -msg timestamp=on -nodefaults -no-user-config -S -no-shutdown -global kvm-pit.lost_tick_policy=discard -chardev socket,id=charmonitor,path='monitor.sock',server,nowait -mon chardev=charmonitor,id=monitor,mode=control -boot menu=on,strict=on -k en-us -rtc base=utc,driftfix=slew -global kvm-pit.lost_tick_policy=delay -no-hpet -smp 1,sockets=1,cores=1,threads=1 -m 512M -realtime mlock=off -device VGA,id=video0,bus=pci.0 -vnc 0.0.0.0:0 -serial stdio
前述のコマンドでVMのコンソールを待ち受ける。別のshellで以下のコマンドを実行することでブロックストレージを接続し、起動することで、VMのコンソールでVMが起動していることを確認できる。
$ qmp-shell -v -p ~/monitor.sock
(QEMU) blockdev-add options='{"driver":"qcow2","id":"virtio0","file":{"driver":"file","filename":"/home/admin/cirros-0.4.0-x86_64-disk.img"}}'
(QEMU) device_add driver=virtio-blk-pci bus=pci.0 scsi=off drive=virtio0 id=virtio-disk0 bootindex=1
(QEMU) cont # 起動

情報

Ubuntu 18.04

IPアドレス: 192.168.11.1
ユーザー: admin
パスワード: QMPisUndocumented

Ubuntu 16.04

IPアドレス: 192.168.11.2
ユーザー: admin
パスワード: QMPisUndocumented

問題のゴール状態

Ubuntu 18.04 においてもVMが起動している

トラブルの概要

VM を管理する QEMU には、プロセスを立ち上げたあとに制御するために QMP と呼ばれる JSON RPC API が存在する。
Ubuntu 16.04(QEMU emulator version 2.5.0 (Debian1:2.5+dfsg-5ubuntu10.30)) から
Ubuntu 18.04 (QEMU emulator version 2.11.1(Debian 1:2.11+dfsg-1ubuntu7.7)) へのアップグレードには破壊的な更新が存在し、
それがもとで BlockDev の追加ができないというトラブルである。

解説

この問題は、バージョンアップへの対応を行えるかという点と QEMU を理解しているかという点を確認する問題でした。
詳しい説明は割愛しますが、 QEMU Machine Protocol(以下QMP)においてデバイスを接続する場合は、
QEMU プロセスと外部(ホストOS側)を接続する blockdev-addnetdev_addと、
QEMU に接続された外部デバイスをゲストOSに接続する device_add という命令を使用します。

今回の問題では blockdev-add の仕様が変わったことによってトラブルが発生していました。
 
http://qemu.11.n7.nabble.com/Adding-an-overlay-with-blockdev-add-fails-with-quot-Parameter-driver-is-missing-quot-td468076.html

つまり、Ubuntu 16.04 にて動作するクエリは以下のとおりですが、
{
  "execute":"blockdev-add",
  "arguments":{
    "options":{
      "driver":"qcow2",
      "id":"virtio0",
      "file":{
        "driver":"file",
        "filename":"/root/cirros.qcow2"
      }
    }
  }
}

Ubuntu 18.04 では以下のようになります。
{
  "execute":"blockdev-add",
  "options":{
    "driver":"qcow2",
    "node_name":"virtio0",
    "file":{
      "driver":"file",
      "filename":"/root/cirros.qcow2"
    }
  }
}

よって,qmp-shellでは以下のように操作をすることで今回の問題が解決します。
$ qemu-system-x86_64 -uuid c01769df-766c-49e3-9c8c-d148e9557975 -name guest=test,debug-threads=on -msg timestamp=on -nodefaults -no-user-config -S -no-shutdown -global kvm-pit.lost_tick_policy=discard -chardev socket,id=charmonitor,path='monitor.sock',server,nowait -mon chardev=charmonitor,id=monitor,mode=control -boot menu=on,strict=on -k en-us -rtc base=utc,driftfix=slew -global kvm-pit.lost_tick_policy=delay -no-hpet -smp 1,sockets=1,cores=1,threads=1 -m 512M -realtime mlock=off -device VGA,id=video0,bus=pci.0 -vnc 0.0.0.0:0 -serial stdio
$ qmp-shell -v -p ~/monitor.sock
(QEMU) blockdev-add driver=qcow2 node-name=virtio0 file='{"driver":"file","filename":"/home/admin/cirros-0.4.0-x86_64-disk.img"}'

(QEMU) device_add driver=virtio-blk-pci bus=pci.0 scsi=off drive=virtio0 id=virtio-disk0 bootindex=1
(QEMU) cont

回答例

この問題のUbuntu 16.04上にあるQEMUとUbuntu 18.04上にあるQEMUのバージョンが異なることにより、受け付けるQMPクエリの構造が異なることで今回のトラブルが発生しておりました。

そのため、QEMUプロセス起動後のQMP Shellでの操作を以下のように変更することで解決します。

(QEMU) blockdev-add driver=qcow2 node-name=virtio0 file='{"driver":"file","filename":"/home/admin/cirros-0.4.0-x86_64-disk.img"}'

(QEMU) device_add driver=virtio-blk-pci bus=pci.0 scsi=off drive=virtio0 id=virtio-disk0 bootindex=1
(QEMU) cont

採点基準

– 18.04でQMPを使ってVMが立ち上がる (100%)